CallMeTechie
DE Login
Home Products Blog About Contact

Docker Installation on Various Operating Systems

🚀 Installation & Setup · Updated 1 month ago

Table of Contents

  1. Prerequisites
  2. Directory layout
  3. Download the setup files
  4. Configure .env
  5. First start
  6. First login
  7. First peer and first route
  8. Verifying the installation
  9. Troubleshooting
  10. Backup and restore
  11. Updates
  12. Migration from older setups

1. Prerequisites

Hardware

Resource Minimum Recommended
CPU 1 vCPU 2 vCPU
RAM 1 GB 2 GB
Disk 20 GB 40 GB (more for long activity logs and Caddy access logs)

Software

  • OS: Any modern Linux distribution (Debian 11+, Ubuntu 22.04+, Fedora, Rocky, Alma, Alpine). Tested on Debian 13.
  • Docker Engine: 24.0 or newer
  • Docker Compose: v2 (part of Docker Engine since 23.0)
  • WireGuard kernel module: present on most modern kernels. The container does not need an external install, but WireGuard capabilities (NET_ADMIN) must be grantable to the container.

DNS

Before starting the container you need one DNS A-record (plus optionally AAAA for IPv6) pointing to the public IP of the host:

gate.example.com.   IN  A   198.51.100.42

GateControl uses this name for two purposes:

  • Admin UI via GC_BASE_URL — Caddy provisions a Let's Encrypt certificate for it automatically on first start.
  • WireGuard endpoint if you also set GC_WG_HOST=gate.example.com. (GC_WG_HOST may be a bare public IP instead, but using the same hostname simplifies peer configs.)

Per-route domains (for reverse-proxy routes you create later) need separate A-records pointing to the same host.

Ports

Port Protocol Purpose Must be reachable from
80 TCP HTTP → HTTPS redirect, ACME HTTP-01 challenge Internet
443 TCP HTTPS admin UI and all reverse-proxy routes Internet
443 UDP HTTP/3 (optional but recommended) Internet
51820 UDP WireGuard VPN endpoint Internet
53 TCP/UDP on 127.0.0.1 and on the VPN subnet gateway IP (10.8.0.1 by default) Internal DNS for VPN peers Container only (loopback and WG interface)

If anything already binds 127.0.0.1:53 on the host (a common cause: NetworkManager-dnsmasq, libvirt-dnsmasq, bind9), the GateControl container will refuse to start. systemd-resolved binds 127.0.0.53 and does not conflict. The entrypoint checks this explicitly and exits with a clear message if it finds another listener.

Open the first four ports in your cloud firewall / iptables / ufw before you start the container.


2. Directory layout

Create a dedicated deploy directory — separate from any cloned source repository. The recommended path is /opt/gatecontrol/:

/opt/gatecontrol/
├── docker-compose.yml    # image, ports, volume
├── .env                  # your config (passwords, domain, etc.)
├── update.sh             # helper to pull latest and restart
└── data/                 # created on first start — holds DB, certs, keys, WG config

Why separate from the source repository:

  • Cleaner mental model: "code" and "config" never get mixed.
  • Safe to clone/wipe/update the source repo without losing production state.
  • One-line backup: tar czf backup.tar.gz /opt/gatecontrol captures everything.
mkdir -p /opt/gatecontrol
cd /opt/gatecontrol

3. Download the setup files

There are three options. They all end with the same files in /opt/gatecontrol/.

Option A — Interactive setup (recommended)

Download and run setup.sh. It installs Docker if missing, walks you through .env values interactively, generates secure secrets, and starts the container:

cd /opt/gatecontrol
curl -fsSLO https://github.com/CallMeTechie/gatecontrol/releases/latest/download/setup.sh
curl -fsSLO https://github.com/CallMeTechie/gatecontrol/releases/latest/download/docker-compose.yml
curl -fsSLO https://github.com/CallMeTechie/gatecontrol/releases/latest/download/.env.example
bash setup.sh

Skip straight to §6 First login — setup.sh does the rest.

Option B — Manual (full control)

cd /opt/gatecontrol
curl -fsSLO https://github.com/CallMeTechie/gatecontrol/releases/latest/download/docker-compose.yml
curl -fsSLO https://github.com/CallMeTechie/gatecontrol/releases/latest/download/.env.example
curl -fsSLO https://raw.githubusercontent.com/CallMeTechie/gatecontrol/master/update.sh
chmod +x update.sh
cp .env.example .env

Proceed to §4 Configure .env.

Option C — Air-gapped / offline

For hosts without internet access during install, download the image tarball from a release:

curl -fsSLO https://github.com/CallMeTechie/gatecontrol/releases/latest/download/gatecontrol-image.tar.gz
docker load < gatecontrol-image.tar.gz
rm gatecontrol-image.tar.gz

Continue with the docker-compose.yml and .env.example from Option B.


4. Configure .env

Edit /opt/gatecontrol/.env. Three values are required; everything else has sensible defaults.

Required

Variable What it is Example
GC_ADMIN_PASSWORD Initial password for the admin account. Read only on first start — later changes happen in the UI. R7!xK2#wPq9$Lm4v
GC_WG_HOST Public IP or hostname your VPN clients dial. Must be reachable from the internet on UDP/51820. gate.example.com or 198.51.100.42
GC_BASE_URL Full URL of the admin UI. Caddy uses the hostname to request a Let's Encrypt certificate. https://gate.example.com

Strongly recommended

Variable Why Example
GC_CADDY_EMAIL Lets Encrypt contacts you for expiry warnings and certificate issues. Without it, certs still work but you get no recovery channel. admin@example.com

Optional — left empty for auto-generation

Variable Default behavior if unset
GC_SECRET A 48-byte session secret is generated on first start and persisted to /data/.session_secret (chmod 600).
GC_ENCRYPTION_KEY A 32-byte AES-256 key is generated and persisted to /data/.encryption_key (chmod 600). Back this up. Restoring a DB without the matching key fails.

See .env.example in the repository for the full reference including WireGuard tuning, rate limits, timeouts, client update repos, and licensing keys.

Edit the file

cd /opt/gatecontrol
nano .env   # or vim, or any editor

Set the three required values. Save and exit.


5. First start

cd /opt/gatecontrol
docker compose up -d
docker compose logs -f

On the first run the entrypoint does several things. Expect to see, in roughly this order:

  1. » Auto-detected egress interface: <name> — the outbound network interface used for VPN NAT. If you see eth0 falling back, it is correct on most cloud VMs; hosts with non-standard NIC names are detected automatically.
  2. » MASQUERADE rule active: 10.8.0.0/24 → <iface> — iptables NAT rule installed.
  3. » Generating WireGuard server keypair... — one-time on first start only. The private key is persisted to ./data/wireguard/wg0.conf with chmod 600.
  4. » Session secret generated and saved — one-time on first start.
  5. » Encryption key generated and saved — one-time on first start.
  6. » Generating dnsmasq config (split-horizon for <hostname> → 10.8.0.1)... — internal DNS config.
  7. » Exporting Caddy JSON from DB... — on a fresh install the DB has no user-defined routes, but the management-UI route (GC_BASE_URL hostname → 127.0.0.1:3000) is injected automatically. You do not need to configure this route by hand.
  8. » Starting services via supervisord...
  9. Caddy boots, acquires Let's Encrypt certificate for the GC_BASE_URL hostname. First cert fetch takes 10–30 seconds. Watch for:
    • obtaining certificate followed by
    • certificate obtained successfully
    • If you see lookup <hostname>: no such host or unable to fetch certificate, DNS is not yet propagated — wait and the ACME client will retry.
  10. WireGuard starts, interface wg0 comes up.
  11. Node.js web application starts on 127.0.0.1:3000. Caddy proxies requests on the GC_BASE_URL hostname to it.

Exit the log tail with Ctrl+C — the container keeps running in the background.


Cookie Settings

We use cookies to improve your experience. Essential cookies are always active.

Privacy Policy
ESC
↑↓ navigate open esc close