For the complete documentation index, see llms.txt. This page is also available as Markdown.

Migrating a 1.6 one-liner installation to 2.x

This guide is meant for instanced deployed using the one-line install script, but the general points also apply to any other Docker Compose deployments.

Due to changes in component architecture introduced in version 2.0 an instance deployed using the one-liner script requires some manual changes to the Docker Compose config. This procedure keeps the existing database and secrets, then uses the migration wizard to adopt the 2.x Edge and Gateway.

Like with any upgrade, before you start make sure to backup your data. If it's possible in your environment, test the upgrade process first on a disposable test instance.

Choose the Gateway network mode

Bridge mode is the current default, but in version 1.6 the compose file generated by the one-line install script used network_mode: host.

Unless you depend on the host networking being used (due to some custom routing setup or client IP requirements for example), we encourage you to switch to bridge mode. This provides better isolation and also enables the service name DNS resolution, so Core can connect to the Gateway by simply using the gateway hostname.

To switch to bridge mode, remove the network_mode: host line and publish the WireGuard UDP port. Use the gateway port of your existing VPN location, which was chosen when the 1.6 one-line script ran, on both sides of the mapping. For example, for a location using port 51820:

ports:
    - "51820:51820/udp"

The gateway listens on the port set in the location settings, so if the mapping uses a different port, clients cannot complete a handshake.

If using the bridge mode you also have to enable masquerade in the gateway, otherwise responses to VPN traffic cannot be routed back to the container. To do that, add the following line to Gateway env:

DEFGUARD_MASQUERADE=true

Clean up 1.6 host networking

The 1.6 gateway ran in the host network namespace and does not remove its WireGuard interface when it stops. After switching to bridge mode, a leftover interface on the host can keep receiving VPN traffic meant for the new gateway container, so clients see the port as open but no handshake completes.

After the 2.x gateway is running in bridge mode:

  1. Make sure no 1.6 gateway container remains:

  2. Check for a leftover WireGuard interface on the host (outside any container) and remove it:

  3. Remove the firewall table left by the 1.6 gateway, if present:

  4. Clear connection tracking entries for the WireGuard port. Clients send keepalive packets, so entries created while the old interface was active may never expire and keep sending traffic to it instead of the container. This requires the conntrack tool:

  5. Restart the gateway:

If you added a masquerade rule on the host for the 1.6 gateway (for example iptables -t nat -A POSTROUTING -o <interface> -j MASQUERADE), it is no longer needed in bridge mode, since DEFGUARD_MASQUERADE=true handles it inside the container. It does not conflict with the gateway, so you can remove it once VPN traffic works. If you persist host firewall rules with netfilter-persistent or iptables-restore, avoid reloading them on a running host: this flushes the rules Docker uses to forward published ports, and the WireGuard port stops reaching the container until Docker is restarted.

Update storage volumes

Since version 2.0 Defguard uses an automatic mTLS setup process to secure the communication between Core and other components (Gateway and Edge). This means that both Gateway and Edge need persistent certificate storage.

Replace the existing /ssl volume for both of them with the following mapping:

For the Core service once the migration wizard is complete you can remove all volume mounts, since all data is stored in the database.

Remove unnecessary environment variables

Following environment variables can be removed, since they are no longer necessary in 2.0. This is a cleanup step, if left as-is these variables will not be read.

Core:

  • DEFGUARD_AUTH_SECRET

  • DEFGUARD_GATEWAY_SECRET

  • DEFGUARD_YUBIBRIDGE_SECRET

  • DEFGUARD_DEFAULT_ADMIN_PASSWORD

  • DEFGUARD_WEBAUTHN_RP_ID

  • DEFGUARD_PROXY_GRPC_CA

  • DEFGUARD_GRPC_KEY

  • DEFGUARD_GRPC_CERT

Edge/Proxy:

  • DEFGUARD_PROXY_GRPC_CERT

  • DEFGUARD_PROXY_GRPC_KEY

  • DEFGUARD_PROXY_URL

Gateway:

  • DEFGUARD_GRPC_URL

  • DEFGUARD_GRPC_CA

  • DEFGUARD_TOKEN

In the .env file, you can also drop the values that only fed those variables: DEFGUARD_AUTH_SECRET, DEFGUARD_GATEWAY_SECRET, DEFGUARD_YUBIBRIDGE_SECRET, DEFGUARD_DEFAULT_ADMIN_PASSWORD, DEFGUARD_WEBAUTHN_RP_ID and DEFGUARD_TOKEN.

Once the migration wizard is complete these additional variables can also be removed from the Core service:

  • DEFGUARD_SECRET_KEY

  • DEFGUARD_URL

  • DEFGUARD_ENROLLMENT_URL

  • DEFGUARD_PROXY_URL

  • DEFGUARD_OPENID_KEY, along with the rsakey.pem volume mount

Update exposed ports

If you decide to keep using Caddy you can just remove the following lines from the Core service, since the communication is now reversed:

If you decide to use the internal CA for securing HTTPS traffic, you have to expose the target HTTP and HTTPS ports:

For the gateway service the port configuration depends on the selected network mode.

Other services

PostgreSQL database

The database service does not need to be changes.

Caddy reverse proxy

Since version 2.0 Defguard provides it's own CA and a separate reverse proxy is not required for serving the Core and Edge UI and API securely over HTTPS.

We recommend leaving Caddy as a fallback if it already works for you, but it can also be removed later.

Update image tags

At this point you can update the CORE_IMAGE_TAG, PROXY_IMAGE_TAG and GATEWAY_IMAGE_TAG environment variables to new 2.x tags.

Run the migration wizard

Pull the new images and start the stack:

Open the Core UI. Core detects the 1.6 database and starts the migration wizard. Follow Migrating from Defguard 1.6 to 2.0 from "Review detected configuration" onwards, using the values below for the one-line deployment.

Edge

The wizard prefills the Edge address from the old Proxy settings. If you kept the proxy service name and DEFGUARD_PROXY_GRPC_PORT: 50052, use proxy and port 50052. If you renamed the service to edge or removed that variable, use the service name and port 50051.

Core and Edge URLs

If you kept Caddy, choose to keep your existing SSL setup for both Core and Edge. If you want Defguard to handle HTTPS instead, see Certificate management and the port summary.

Gateway

When the wizard asks for the Gateway address:

  • Bridge mode: use gateway and port 50066.

  • Host mode: the name gateway does not resolve, because the Gateway is not on the Compose network. Use a stable IP address of the host instead, for example its LAN IP. Make sure the address is static or reserved in DHCP. It becomes part of the Gateway's certificate and stored URL, so changing it later breaks the connection to Core.

    Core connects to this address from the Docker Compose network, so the host firewall must allow TCP 50066 from the Compose network's subnet. Block port 50066 everywhere else, especially on public interfaces. Until the Gateway is adopted, anyone who can reach this port can adopt it.

After the wizard completes

  1. Verify the migration as described in Verify the migration, including a VPN connection from an existing device and access to a LAN resource.

  2. Back up the new edge/certs and gateway/certs directories. They hold the adoption certificates and are not stored in the database.

  3. Optionally remove the post-migration variables and the Core volume mounts listed above, then run docker compose up -d again.

Last updated

Was this helpful?