1. Plan the installation

Install Docker Engine and Docker Compose v2 using the official Docker Engine instructions and Compose plugin instructions. Choose only the public names you need.

PurposeExampleRequired record
Administration panelpanel.example.comA to the server IPv4 address
VPN endpointvpn.example.comA to the server IPv4 address
DNS over HTTPSdns.example.comA to the server IPv4 address
Mail servermail.example.comA to the server IPv4 address
Mail domainexample.comMX to mail.example.com

Do not publish an AAAA record unless IPv6 is configured on the host, firewall, reverse proxy, and relevant NetSmart service.

2. Create public DNS records

panel.example.com.  A   203.0.113.10
vpn.example.com.    A   203.0.113.10
dns.example.com.    A   203.0.113.10
mail.example.com.   A   203.0.113.10
example.com.        MX  10 mail.example.com.

Replace the documentation address with the server’s public IPv4 address, then verify propagation:

dig +short panel.example.com A
dig +short vpn.example.com A
dig +short example.com MX

For internet mail, set the public IP’s PTR record to mail.example.com. Keep VPN and mail hostnames in DNS-only mode when the DNS provider offers an HTTP proxy; HTTP proxies do not carry WireGuard UDP or standard mail protocols.

3. Prepare the project and secrets

Create a deployment directory, then copy the production docker-compose.yml and environment template from the NetSmart Docker Hub page.

mkdir -p netsmart
cd netsmart
cp .env.example .env

Replace every example secret in .env:

MYSQL_ROOT_PASSWORD=replace-with-a-long-random-root-password
MYSQL_DATABASE=netsmart_db
MYSQL_USER=netsmart_user
MYSQL_PASSWORD=replace-with-a-long-random-database-password
MYSQL_HOST_PORT=3307

NETSMART_HTTP_BIND=127.0.0.1
NETSMART_HTTP_PORT=8080
WIREGUARD_ENDPOINT_HOST=vpn.example.com

SNMP_COMMUNITY=replace-with-a-private-random-community

Keep the HTTP bind address on loopback when Nginx or Apache runs on the same server. Create required local files, restrict them, and pin the image:

printf '{}\n' > appsettings.json
mkdir -p certs
chmod 600 .env appsettings.json
image: ssiroos/netsmartapp:1.0.12

Remove build: . from docker-compose.yml when the server should pull the published image.

4. Enable host networking requirements

sudo sysctl -w net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-netsmart-vpn.conf
sudo sysctl --system
test -c /dev/net/tun && echo "TUN device is ready"

The NetSmart Compose service must retain:

network_mode: host
cap_add:
  - NET_ADMIN
devices:
  - /dev/net/tun:/dev/net/tun

5. Start and inspect NetSmart

docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps

Both netsmart-mysql and netsmart-app should become healthy. If they do not:

docker compose logs --tail=200 mysql
docker compose logs --tail=200 netsmart
curl -I http://127.0.0.1:8080/

6. Configure the panel domain and HTTPS

Install Nginx and create a virtual host for the panel:

server {
    listen 80;
    listen [::]:80;
    server_name panel.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d panel.example.com
sudo certbot renew --dry-run

See the official Certbot documentation. After HTTPS works, do not expose port 8080 publicly.

7. Complete the mandatory first login

Username: sa
Password: sa123456

NetSmart immediately opens Change Default Password. Set a unique password of at least 16 characters; the initial password cannot be retained or reused. Then confirm the initial password no longer works, create a named administrator, enable CAPTCHA or MFA in Login Config, restrict panel access where possible, and keep MySQL port 3307 on loopback.

8. Register a commercial installation

Individual non-commercial use is free. Commercial or company use requires a USD $99 annual licence for each registered NetSmart service domain. Each additional domain requires its own annual licence. Open the panel through its final HTTPS hostname before registration because that hostname defines the licensed domain.

  1. Open Register as an administrator.
  2. Confirm the Service URL is the final HTTPS panel URL.
  3. Open the generated registration link and sign in to the licence portal.
  4. Register the displayed device ID.
  5. Copy the issued token into Licence token and select Save Token.
  6. Confirm that the licence status is Active.

Treat the token as a secret. It is stored in MySQL, so preserve the database during upgrades.

9. Configure AmneziaWG

Allow inbound UDP 51820 in cloud and host firewalls. Do not proxy it through Nginx. In WireGuard / AmneziaWG Settings, start with:

Protocol: AmneziaWG
Interface: wg0
Server address: 10.8.0.1/24
Listen port: 51820
Endpoint host: vpn.example.com
Client allowed IPs: 0.0.0.0/0
Persistent keepalive: 25
IPv4 forwarding and NAT: enabled
Internet interface: auto

Choose client-supported obfuscation values, apply and start the service, and give every device a unique peer address such as 10.8.0.2/32. Download each configuration only to its intended device. Test from outside the server network and confirm a recent handshake plus nonzero RX/TX counters.

10. Configure optional DNS over HTTPS

Obtain a certificate for dns.example.com, verify its files, then proxy only the DNS query endpoint:

server {
    listen 443 ssl;
    server_name dns.example.com;
    ssl_certificate /etc/letsencrypt/live/dns.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dns.example.com/privkey.pem;

    location = /dns-query {
        proxy_pass http://127.0.0.1:8080/dns-query;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
    location / { return 404; }
}

Enable NetSmart DNS before configuring clients with https://dns.example.com/dns-query.

11. Configure an optional mail domain

mail.example.com.               A     203.0.113.10
example.com.                    MX    10 mail.example.com.
example.com.                    TXT   "v=spf1 mx -all"
default._domainkey.example.com. TXT   "v=DKIM1; k=rsa; p=PUBLIC_KEY"
_dmarc.example.com.             TXT   "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

Set PTR to mail.example.com. Add the mail domain and hostname, generate or securely mount the DKIM key, publish the generated DKIM record, configure a PFX certificate, and test inbound and outbound delivery. Use submission port 587 with STARTTLS or SMTPS 465 for authenticated clients; port 25 is server-to-server SMTP.

12. Apply a least-access firewall policy

Always allow SSH from administrator addresses and HTTP/HTTPS for certificate issuance and the panel. Open service ports only when that service is enabled:

PortsPurpose and scope
22/tcpSSH; administrator addresses only
80, 443/tcpCertificates, HTTPS panel, and optional DoH
53/tcp, 53/udpDNS
67/udpDHCP; LAN only
88/tcp, 88/udpKerberos; trusted networks
123/udpNTP; normally trusted networks
161/udpSNMP; monitoring network
389/tcpLDAP; trusted networks
25, 465, 587/tcpSMTP, SMTPS, and submission
110, 143/tcpPOP3 and IMAP; disable unless required
51820/udpWireGuard or AmneziaWG

Never expose MySQL 3307, Ollama 11434, or panel backend 8080 publicly.

13. Verify and back up

docker compose ps
docker compose logs --tail=200 netsmart
curl -I https://panel.example.com
docker inspect netsmart-app \
  --format 'network={{.HostConfig.NetworkMode}} capabilities={{json .HostConfig.CapAdd}}'

Expect healthy containers, valid HTTPS, host networking, NET_ADMIN, a changed sa password, and only intentional listeners. Back up MySQL, data-protection keys, VPN configuration, TLS certificates, DKIM private keys, appsettings.json, .env, and optional Samba AD volumes together. Protect and test the backup. Never commit secrets, tokens, database data, or VPN client configurations to Git.

14. Update safely

Read the changelog and back up first. Pin the intended image version, then:

docker compose pull netsmart
docker compose up -d --force-recreate netsmart
docker compose ps
docker compose logs --tail=200 netsmart

Verify login, health, every enabled service, VPN handshakes, DNS resolution, and mail delivery after each update.

Completion checklist

  • Public DNS records resolve to the server.
  • All example secrets were replaced.
  • IPv4 forwarding survives reboot.
  • MySQL and NetSmart are healthy.
  • The panel uses valid HTTPS and port 8080 is private.
  • The initial password was changed and a named administrator plus MFA were configured.
  • The commercial licence is active when required.
  • VPN DNS and UDP 51820 work, with a unique address per peer.
  • Only required service ports are open.
  • Mail DNS, PTR, TLS, SPF, DKIM, and DMARC are configured when mail is enabled.
  • A backup exists and restoration was tested.

Return to NetSmart Open Docker Hub