
This article provides a guide demonstrating how to install Dokploy on Ubuntu VPS.
What is Dokploy?
Dokploy is a self-hosted Platform as a Service, or PaaS, that provides a web interface for deploying and managing applications, databases, Docker Compose projects, domains, SSL certificates, environment variables, and automated deployments.
It is designed as a self-hosted alternative to services such as Heroku, Vercel, and Netlify. Dokploy uses Docker for application workloads and Traefik for HTTP and HTTPS routing.
This guide demonstrates how to install Dokploy on a fresh Ubuntu VPS and prepare it for production use.
Deployment overview
The completed installation will use the following general architecture:
Internet | | TCP 80 and 443 v Traefik reverse proxy | +-- Dokploy administration panel | +-- Application containers | +-- Database containers | +-- Docker Compose projects
Dokploy installs and manages several components, including:
- Docker Engine
- Docker Swarm
- Dokploy
- PostgreSQL for Dokploy’s internal data
- Traefik for reverse proxying and TLS
- Docker networks and persistent volumes
For a basic single-server deployment, Dokploy, Traefik, application containers, and databases can all run on the same VPS.
Requirements and planning
Recommended server specifications
Dokploy officially recommends at least:
- 2 GB RAM
- 30 GB storage
- A supported Linux distribution
- Available ports 80, 443, and 3000
Ubuntu 20.04, 22.04, and 24.04 LTS are among the officially tested Ubuntu versions.
Although 2 GB is the documented minimum, a production installation should generally start with:
CPU: 2 or more vCPU Memory: 4 GB RAM or more Storage: 50 GB SSD or more Network: Public IPv4 address OS: Ubuntu 24.04 LTS
Use additional CPU, memory, and storage when the server will:
- Build large applications
- Run several databases
- Host multiple customer applications
- Build Node.js, Java, Rust, or other memory-intensive projects
- Retain many Docker images
- Run monitoring or log-collection services
A small swap file is also useful as an emergency buffer, although swap should not replace adequate physical memory.
Required network ports
The standard installation requires these inbound ports:
| Port | Protocol | Purpose |
|---|---|---|
| 22 | TCP | SSH administration |
| 80 | TCP | HTTP and Let’s Encrypt validation |
| 443 | TCP | HTTPS application traffic |
| 443 | UDP | HTTP/3, when enabled through Traefik |
| 3000 | TCP | Initial Dokploy administration interface |
Ports 80, 443, and 3000 must be unused before the installation begins. The installer stops when another service already occupies one of these ports.
Port 3000 should only remain publicly accessible long enough to create the initial administrator account and configure a secure domain.
See Also: How to Install Coroot on Ubuntu VPS
Choose a hostname
Select a fully qualified hostname for the Dokploy control panel.
For example:
dokploy.example.com
Create an A record pointing the hostname to the VPS public IPv4 address:
Type: A Name: dokploy Value: 203.0.113.20 TTL: 300
When IPv6 is configured and working correctly, you may also create an AAAA record.
Verify DNS resolution before configuring HTTPS:
dig +short dokploy.example.com
Or:
getent ahostsv4 dokploy.example.com
The returned address should match the VPS public IPv4 address.
Compare Ubuntu VPS Plans
How to Install Dokploy on Ubuntu VPS
To install Dokploy on Ubuntu VPS, follow the steps outlined below:
-
Connect to the VPS
Connect as root:
ssh root@203.0.113.20
Alternatively, connect as a sudo-enabled administrator:
ssh administrator@203.0.113.20
Then open a root shell:
sudo -i
The Dokploy installation script must run with root privileges.
-
Verify the operating system
Display the Ubuntu release:
cat /etc/os-release
Example:
PRETTY_NAME="Ubuntu 24.04.2 LTS" NAME="Ubuntu" VERSION_ID="24.04"
Check the kernel:
uname -r
Check the server architecture:
dpkg --print-architecture
Most VPS installations should report:
amd64
Dokploy should be installed directly on a VPS or virtual machine, not inside a regular Docker container. The official installation script checks for containerized environments and exits when it detects one.
-
Update Ubuntu
Update the package index and install available updates:
apt update apt full-upgrade -y
Install common administration utilities:
apt install -y \ curl \ wget \ ca-certificates \ gnupg \ jq \ unzip \ nano \ vim \ git \ ufw \ dnsutils \ htop \ lsofReboot when the upgrade installed a new kernel or important system libraries:
reboot
Reconnect after the server restarts.
-
Configure the hostname
Set a descriptive system hostname:
hostnamectl set-hostname dokploy01.example.com
Confirm it:
hostnamectl
Add the hostname to
/etc/hostswhen necessary:nano /etc/hosts
Example:
127.0.0.1 localhost 127.0.1.1 dokploy01.example.com dokploy01
Do not map the public control-panel hostname to
127.0.0.1if applications on the server must resolve it to the public address. -
Configure the timezone
List available timezones:
timedatectl list-timezones
Set the appropriate timezone:
timedatectl set-timezone America/Chicago
Verify the setting:
timedatectl
Dokploy also supports a configurable
TZenvironment variable for customized installations. -
Configure time synchronization
Check the system clock:
timedatectl status
Enable systemd time synchronization:
timedatectl set-ntp true
Confirm that synchronization is active:
timedatectl timesync-status
Accurate time is important for TLS certificates, authentication, scheduled jobs, logs, and database operations.
-
Add swap space
Check whether swap is already available:
See Also: cPanel Shared Hosting Server Specs
swapon --show free -h
For a small VPS with no swap, create a 2 GB swap file:
fallocate -l 2G /swapfile
Restrict access:
chmod 600 /swapfile
Initialize it:
mkswap /swapfile
Enable it:
swapon /swapfile
Make it persistent:
echo '/swapfile none swap sw 0 0' >> /etc/fstab
Set a conservative swappiness value:
cat > /etc/sysctl.d/99-dokploy-memory.conf <<'EOF' vm.swappiness=10 vm.vfs_cache_pressure=50 EOF
Apply the settings:
sysctl --system
Verify:
swapon --show free -h
-
Inspect ports 80, 443, and 3000
Run:
ss -lntup | grep -E ':(80|443|3000)\b' || true
You can also check each port individually:
lsof -iTCP:80 -sTCP:LISTEN lsof -iTCP:443 -sTCP:LISTEN lsof -iTCP:3000 -sTCP:LISTEN
There should be no output.
Common conflicting services include:
- Apache
- Nginx
- Caddy
- An existing Traefik instance
- A Node.js application using port 3000
- Another hosting control panel
To stop Apache:
systemctl disable --now apache2
To stop Nginx:
systemctl disable --now nginx
To stop Caddy:
systemctl disable --now caddy
Remove a conflicting web server only when it is no longer needed:
apt remove --purge -y apache2 apache2-utils
Or:
apt remove --purge -y nginx nginx-common
Recheck the ports:
ss -lntup | grep -E ':(80|443|3000)\b' || true
-
Check for an existing Docker Swarm
If Docker is already installed, inspect its Swarm status:
docker info 2>/dev/null | grep -i swarm || true
Do not run the normal Dokploy installer on a server already participating in a production Docker Swarm. The official installer forces the node to leave its current Swarm and initializes a new one, which can disrupt existing services.
A clean VPS is strongly recommended.
-
Configure a provider-level firewall
When your VPS provider offers a network firewall, allow:
TCP 22 from your trusted administration IP addresses TCP 80 from anywhere TCP 443 from anywhere UDP 443 from anywhere, when HTTP/3 is desired TCP 3000 temporarily from your trusted administration IP
A provider firewall is especially useful for restricting the initial port 3000 exposure.
For example, permit port 3000 only from:
198.51.100.25/32
After configuring a domain and HTTPS, remove the port 3000 rule.
-
Configure UFW
Before enabling UFW, permit SSH:
ufw allow OpenSSH
Or restrict SSH to your workstation address:
ufw allow from 198.51.100.25 to any port 22 proto tcp
Permit HTTP and HTTPS:
ufw allow 80/tcp ufw allow 443/tcp ufw allow 443/udp
Temporarily permit the Dokploy interface from your IP:
See Also: How to Migrate Your Website from A2 Hosting to Rad Web Hosting
ufw allow from 198.51.100.25 to any port 3000 proto tcp
Set default policies:
ufw default deny incoming ufw default allow outgoing
Enable UFW:
ufw enable
Review the rules:
ufw status numbered
Important Docker firewall consideration
Docker creates its own packet-filtering and port-publication rules. Published container ports may therefore require controls beyond ordinary UFW rules. Docker recommends placing custom filtering rules in the
DOCKER-USERchain rather than disabling Docker’s firewall management, because disabling Docker-managed rules can break container networking.For this reason, use the provider-level firewall as the primary restriction for the temporary port 3000 exposure whenever possible.
-
Review the installer before running it
The official one-line installation command is:
curl -sSL https://dokploy.com/install.sh | sh
For a production server, it is safer to download and inspect the script first:
curl -fsSL https://dokploy.com/install.sh -o /root/install-dokploy.sh
Review it:
less /root/install-dokploy.sh
Optionally calculate a local checksum for your records:
sha256sum /root/install-dokploy.sh
Make it executable:
chmod 700 /root/install-dokploy.sh
Run it:
/root/install-dokploy.sh
The script installs Docker automatically when Docker is not already present and deploys the required Dokploy services.
-
Install the latest stable release explicitly
To explicitly select the latest stable release:
export DOKPLOY_VERSION=latest /root/install-dokploy.sh
Alternatively:
curl -fsSL https://dokploy.com/install.sh | DOKPLOY_VERSION=latest sh
Avoid the
canaryrelease on production systems. Canary builds are development versions:export DOKPLOY_VERSION=canary curl -sSL https://dokploy.com/install.sh | sh
Use canary only for testing or when instructed by the Dokploy project.
The installer supports
latest,canary, and specific release tags throughDOKPLOY_VERSION. -
Pin a specific Dokploy version
For a controlled production rollout, choose a specific current release from the official Dokploy release page and pass the tag:
export DOKPLOY_VERSION=v0.29.13 /root/install-dokploy.sh
At the time this guide was prepared, the official release list identified
v0.29.13as the latest release. Always verify the current release and security notes before installation.Pinning provides more predictable behavior, while
latestautomatically selects the newest stable version available to the installer. -
Specify the Docker Swarm advertise address
On a VPS with multiple network interfaces, private networking, or a VPN, the installer may select the wrong address.
List IPv4 addresses:
See Also: Migrating Email Accounts Using Imapsync (Quick 5 Minute Guide)
ip -4 address show
Display the default route:
ip route
Run the installer with an explicit Swarm advertise address:
curl -fsSL https://dokploy.com/install.sh | \ ADVERTISE_ADDR=203.0.113.20 shWhen using
sudo, pass the environment variable inline:curl -fsSL https://dokploy.com/install.sh | \ sudo ADVERTISE_ADDR=203.0.113.20 shDo not assume that an exported variable will survive
sudo, becausesudonormally resets the environment. Dokploy’s documentation specifically recommends passingADVERTISE_ADDRinline in this situation.When the VPS has a reliable private network, that private address may be preferable for future multi-node Swarm communication.
-
Avoid Docker network conflicts
Docker networks must not overlap with:
- The VPS private network
- A WireGuard network
- A Tailscale network
- Office or management networks
- Other container platforms
For example, initialize Dokploy with a custom Docker Swarm address pool:
export DOCKER_SWARM_INIT_ARGS="--default-addr-pool 172.20.0.0/16 --default-addr-pool-mask-length 24" curl -fsSL https://dokploy.com/install.sh | sh
Choose a range that does not conflict with existing routes.
Inspect current routes first:
ip route
The official installer supports
DOCKER_SWARM_INIT_ARGSspecifically for avoiding address conflicts with provider networks and VPCs. -
Check Docker
Verify the Docker service:
systemctl status docker --no-pager
Check its version:
docker version
Display general information:
docker info
Confirm that Docker Swarm is active:
docker info | grep -i swarm
Expected:
Swarm: active
Check the node:
docker node ls
A single-server installation should show the local server as a Swarm manager.
-
Check Dokploy services
List Docker Swarm services:
docker service ls
You should normally see services such as:
dokploy dokploy-postgres
Traefik may appear as a standalone container, depending on the installed Dokploy version.
List running containers:
docker ps
Current self-hosted Dokploy installations normally include:
- Dokploy
- PostgreSQL
- Traefik
Older releases before Dokploy 0.29.9 may also include Redis; newer self-hosted versions no longer use it.
-
Check listening ports
Run:
ss -lntup | grep -E ':(80|443|3000)\b'
Expected listeners include:
0.0.0.0:80 0.0.0.0:443 0.0.0.0:3000
Check the local Dokploy response:
curl -I http://127.0.0.1:3000
Also test the server’s public address:
curl -I http://203.0.113.20:3000
-
Inspect logs
Dokploy logs:
docker service logs --tail 100 dokploy
Follow the logs live:
docker service logs -f dokploy
PostgreSQL logs:
docker service logs --tail 100 dokploy-postgres
Traefik logs:
docker logs --tail 100 dokploy-traefik
Follow Traefik logs:
See Also: Install Coder on AlmaLinux VPS and Connect Workspace to VS Code (5 Minute Quick-Start Guide)
docker logs -f dokploy-traefik
These are the primary log commands recommended in Dokploy’s troubleshooting documentation.
-
Open the Dokploy dashboard
Open the following address in a browser:
http://203.0.113.20:3000
You should see the initial account-creation page.
Create the first administrator account using:
- A unique email address
- A long, randomly generated password
- Credentials not reused on other systems
The first account becomes the Dokploy administrator.
Do not leave the initial registration page exposed longer than necessary.
-
Enable multifactor authentication
After logging in, open the account security settings and enable two-factor authentication when available.
Store the following safely:
- TOTP secret or QR-code recovery data
- Recovery codes
- Administrative password
- Server SSH recovery credentials
Keep recovery data outside the Dokploy server.
-
Confirm DNS
Confirm the panel hostname resolves to the VPS:
dig +short dokploy.example.com A
Expected:
203.0.113.20
Check from an external computer as well:
nslookup dokploy.example.com
Do not request a certificate until public DNS points to the correct server.
-
Add the Dokploy panel domain
Inside Dokploy:
- Open the server or web-server settings.
- Locate the domain configuration for the Dokploy panel.
- Add:
dokploy.example.com
- Enable HTTPS.
- Select Let’s Encrypt as the certificate provider.
- Save the configuration.
- Allow Dokploy and Traefik to generate the routing configuration.
The panel should become available at:
https://dokploy.example.com
Dokploy supports domain TLS configurations including Let’s Encrypt, Cloudflare, and custom certificates.
-
Verify the certificate
Test HTTPS:
curl -I https://dokploy.example.com
Inspect the certificate:
openssl s_client \ -connect dokploy.example.com:443 \ -servername dokploy.example.com \ </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject -datesConfirm:
- The certificate subject matches the hostname.
- The certificate is currently valid.
- The issuer is trusted.
- HTTP redirects to HTTPS as expected.
Test the redirect:
curl -I http://dokploy.example.com
-
Cloudflare considerations
When the domain uses Cloudflare:
- Initially set the DNS record to DNS only.
- Complete the origin certificate issuance.
- Verify direct HTTPS access.
- Enable Cloudflare proxying afterward, when desired.
- Use Full (strict) SSL mode whenever the origin has a valid certificate.
Dokploy’s Cloudflare documentation describes end-to-end encrypted configurations and the use of strict origin validation.
Avoid Cloudflare’s Flexible mode because it does not provide encrypted traffic between Cloudflare and the origin server.
-
Confirm the domain works first
Before removing direct access, verify:
https://dokploy.example.com
Test it from:
- Your normal browser
- A private or incognito browser window
- A separate internet connection where possible
Do not continue until HTTPS access works reliably.
-
Remove Dokploy’s published port
Dokploy officially recommends removing the direct
IP:3000publication after the secure domain is working.See Also: 6 Ways to Customize the VPS Panel With Your Branding – Cloud Admin Guide
Run:
docker service update \ --publish-rm "published=3000,target=3000,mode=host" \ dokployThis removes public port 3000 while allowing Traefik to reach Dokploy over the internal Docker network.
Verify:
docker service inspect dokploy \ --format '{{json .Endpoint.Spec.Ports}}' | jqCheck listening ports:
ss -lntup | grep ':3000\b' || true
The public listener should be gone.
-
Remove firewall access to port 3000
List UFW rules:
ufw status numbered
Delete the rule by number:
ufw delete RULE_NUMBER
For example:
ufw delete 4
Also remove the corresponding rule from the VPS provider firewall.
The final public exposure should normally be:
22/tcp restricted to trusted management sources 80/tcp public 443/tcp public 443/udp public when HTTP/3 is used
-
Create a project
In Dokploy:
- Open Projects.
- Select Create Project.
- Enter a project name:
test-project
- Create an environment:
production
- Add an application.
-
Deploy from a public Git repository
Choose a public Git provider or repository URL.
Configure:
Repository: https://github.com/example/example-app.git Branch: main
Select the appropriate build method:
- Dockerfile
- Docker Compose
- Nixpacks
- Railpack
- Static site, where supported
Specify the application port. For example:
3000
Add required environment variables, then click Deploy.
Monitor:
- Build logs
- Deployment logs
- Container logs
- Health status
-
Assign an application domain
Create another DNS record:
Type: A Name: app Value: 203.0.113.20
Inside the application:
- Open Domains.
- Add:
app.example.com
- Enter the application’s internal container port.
- Enable HTTPS.
- Select Let’s Encrypt.
- Save and redeploy when prompted.
Open:
https://app.example.com
Do not publish the application’s internal port directly unless external port access is specifically required. Let Traefik route normal HTTP and HTTPS traffic.
-
Add an SSH key for private repositories
Create a dedicated key on a secure administration workstation or through Dokploy’s SSH-key interface.
Command-line example:
ssh-keygen -t ed25519 -C "dokploy-deploy-key"
Use a dedicated deployment key rather than a personal administrative key.
Add the public key to:
- GitHub deploy keys
- GitLab deploy keys
- Bitbucket access keys
- Your private Git server
Store the private key in Dokploy’s SSH-key configuration.
Grant read-only repository access unless Dokploy specifically needs write access.
-
Configure automatic deployment
For supported Git providers:
- Add the Git provider integration.
- Authorize only the required repositories.
- Select the branch to deploy.
- Enable automatic deployment.
- Configure watch paths when using a monorepo.
- Trigger a test commit.
- Confirm that the webhook starts a deployment.
Use separate credentials or Git applications for production environments.
-
Create a non-root SSH administrator
Create an account:
See Also: Ultimate Guide to VPS Security Hardening
adduser deployadmin
Grant sudo access:
usermod -aG sudo deployadmin
Copy the SSH key configuration:
rsync --archive --chown=deployadmin:deployadmin \ /root/.ssh /home/deployadmin/Test the new account in a separate terminal:
ssh deployadmin@203.0.113.20
Confirm sudo access:
sudo -i
Do not disable root access until the new account has been tested successfully.
-
Harden SSH
Create a configuration drop-in:
nano /etc/ssh/sshd_config.d/99-hardening.conf
Example:
PermitRootLogin prohibit-password PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes X11Forwarding no AllowTcpForwarding yes MaxAuthTries 4 LoginGraceTime 30
Validate the configuration:
sshd -t
Reload SSH:
systemctl reload ssh
Keep the current SSH session open while testing a new connection.
Once key-based access is confirmed, you may change:
PermitRootLogin no
-
Install Fail2ban
Install it:
apt install -y fail2ban
Create a local configuration:
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF' [sshd] enabled = true port = ssh backend = systemd maxretry = 5 findtime = 10m bantime = 1h EOF
Enable it:
systemctl enable --now fail2ban
Check status:
fail2ban-client status fail2ban-client status sshd
-
Enable automatic security updates
Install the package:
apt install -y unattended-upgrades
Enable automatic configuration:
dpkg-reconfigure -plow unattended-upgrades
Verify timers:
systemctl list-timers | grep apt
Review:
cat /etc/apt/apt.conf.d/20auto-upgrades
Application maintenance windows should still be planned for kernel upgrades and Docker restarts.
-
Protect Dokploy accounts
Use these account practices:
- Enable two-factor authentication.
- Use separate accounts for each administrator.
- Do not share the owner account.
- Grant the minimum required permissions.
- Remove former users promptly.
- Rotate API keys and Git credentials.
- Restrict provider integrations to required repositories.
- Keep recovery codes offline.
Dokploy supports owner, administrator, and member roles with different access levels. The owner has the highest privileges, while members can be assigned narrower permissions.
-
Do not expose databases unnecessarily
Applications connected to a database on an internal Docker network should use internal credentials and hostnames.
Avoid publishing:
5432 3306 27017 6379
to the public internet unless external database access is explicitly required.
When external access is required:
- Restrict the source IP.
- Require TLS.
- Use strong credentials.
- Create a limited database user.
- Prefer VPN or SSH-tunnel access.
Dokploy distinguishes internal database connections from externally exposed connections; internal connections avoid unnecessary public exposure.
-
Configure an S3-compatible destination
Dokploy supports S3-compatible destinations for backups.
See Also: Connect BigBlueButton Server to Moodle LMS for Integrated eLearning
Possible storage targets include:
- Amazon S3
- Cloudflare R2
- Backblaze B2 S3
- Wasabi
- MinIO
- Other S3-compatible object stores
In Dokploy:
- Open Settings.
- Open Destinations or S3 Destinations.
- Create a destination.
- Enter the endpoint, region, bucket, access key, and secret key.
- Test the connection.
Use a dedicated bucket and limited-access credentials.
-
Back up Dokploy itself
Navigate to:
Web Server → Backups
Create a backup configuration and choose the S3 destination.
A full Dokploy backup includes:
- The Dokploy PostgreSQL database
- The
/etc/dokployfilesystem - A compressed backup archive uploaded to the configured S3 destination
Dokploy’s restoration process can restore both its internal database and
/etc/dokployconfiguration.Example daily schedule:
30 3 * * *
This runs at 3:30 a.m. according to the applicable server or application timezone.
-
Back up application databases
For each managed database:
- Open the database.
- Select Backups.
- Choose the S3 destination.
- Enter the database name.
- Set a schedule.
- Enter a unique object prefix.
- Enable the backup.
- Click Test.
- Confirm the backup appears in the bucket.
Dokploy provides scheduled database backups and a test function that performs an immediate backup to confirm the destination is working.
-
Back up persistent volumes
Applications using persistent Docker named volumes need separate volume backups.
Dokploy supports volume backups to S3-compatible storage. This is useful for:
- SQLite data
- User uploads
- Application-generated files
- CMS content
- Persistent service data
Dokploy volume backups work with Docker named volumes, not arbitrary bind mounts.
Document every application’s persistence model so that database and filesystem data are both protected.
-
Test restoration
A backup is not complete until it has been restored successfully.
At least quarterly:
- Provision a temporary VPS.
- Install a compatible Dokploy version.
- Restore the Dokploy backup.
- Restore one or more application databases.
- Restore persistent volumes.
- Update temporary DNS or local hosts-file entries.
- Test the applications.
- Document the recovery time and any missing steps.
- Destroy the temporary environment after testing.
Store backup credentials separately from the production server.
-
Monitor host resources
Check CPU and memory:
htop
Check memory:
free -h
Check storage:
df -hT
Check inode usage:
df -ih
Check Docker disk consumption:
docker system df
Check container utilization:
docker stats
Check failed services:
systemctl --failed
Storage deserves special attention because application builds and old Docker images can consume space rapidly. Dokploy notes that insufficient storage can prevent its PostgreSQL database and web interface from operating normally.
-
Configure Docker log rotation
Check the current Docker configuration:
See Also: Announcing RWHServers for WHMCS: PAYG VPS & Dedicated Server Reselling
cat /etc/docker/daemon.json 2>/dev/null || echo "No daemon.json present"
For a new installation with no existing configuration, create:
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<'EOF' { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } } EOFValidate the JSON:
jq . /etc/docker/daemon.json
Restarting Docker interrupts containers briefly, so perform this during a maintenance window:
systemctl restart docker
Confirm Docker returns:
docker ps docker service ls
Do not overwrite an existing
daemon.json. Merge new properties into the existing JSON object. -
Clean unused Docker data carefully
Review usage first:
docker system df
Remove unused build cache:
docker builder prune
Remove unused images:
docker image prune
Remove unused networks:
docker network prune
A more aggressive cleanup is:
docker system prune -a
This may remove images needed for fast rollback or redeployment. Review the prompt carefully and verify backups before using aggressive pruning on production systems.
Do not add automatic volume pruning without thoroughly understanding the effect.
-
Back up before updating
Before every update:
- Create a fresh Dokploy backup.
- Confirm the backup is present in object storage.
- Back up important application databases.
- Review the release notes.
- Confirm available disk space.
- Record the currently installed version.
- Schedule a maintenance window.
Display current services:
docker service ls
Display the current Dokploy image:
docker service inspect dokploy \ --format '{{.Spec.TaskTemplate.ContainerSpec.Image}}' -
Update to the latest version
Run the official update command:
curl -fsSL https://dokploy.com/install.sh | sh -s update
Dokploy documents this command as the standard method for updating to the latest version.
Monitor the update:
docker service ps dokploy
Follow logs:
docker service logs -f --tail 100 dokploy
Verify afterward:
docker service ls docker ps curl -I https://dokploy.example.com
-
Update to a specific release
To deploy a specific version:
export DOKPLOY_VERSION=v0.29.13 curl -fsSL https://dokploy.com/install.sh | sh -s update
When invoking through
sudo, pass the variable inline or preserve the environment appropriately:curl -fsSL https://dokploy.com/install.sh | \ sudo DOKPLOY_VERSION=v0.29.13 sh -s updateUse only documented release tags from the official Dokploy repository.
-
The installer reports that a port is already in use
Identify the process:
ss -lntup | grep -E ':(80|443|3000)\b'
Or:
fuser -v 80/tcp fuser -v 443/tcp fuser -v 3000/tcp
Check common services:
systemctl status nginx apache2 caddy --no-pager
Stop the conflicting service:
See Also: How to Deploy gVisor on Ubuntu VPS
systemctl disable --now nginx
Run the installer again only after all three required ports are free.
-
Docker Swarm initialization fails
A typical error is:
must specify a listening address because the address to advertise is not recognized as a system address
List server addresses:
ip -4 addr
Choose the correct address and rerun:
curl -fsSL https://dokploy.com/install.sh | \ sudo ADVERTISE_ADDR=203.0.113.20 shDokploy recommends explicitly setting
ADVERTISE_ADDRwhen automatic detection fails or the server has multiple interfaces. -
The dashboard is unreachable
Check services:
docker service ls docker ps
Check port 3000:
ss -lntup | grep ':3000\b'
Test locally:
curl -v http://127.0.0.1:3000
Check logs:
docker service logs --tail 200 dokploy docker service logs --tail 200 dokploy-postgres docker logs --tail 200 dokploy-traefik
Check firewall rules:
ufw status verbose
Check provider firewall rules as well.
If the Dokploy service started before PostgreSQL and cannot resolve
dokploy-postgres, restart it by scaling down and back up:docker service scale dokploy=0 docker service scale dokploy=1
This is the recovery procedure documented for a Dokploy/PostgreSQL startup race condition.
-
Traefik is not routing applications
Check Traefik:
docker ps --filter name=dokploy-traefik docker logs --tail 200 dokploy-traefik
Restart it:
docker restart dokploy-traefik
Inspect the Dokploy Traefik configuration:
find /etc/dokploy/traefik -maxdepth 3 -type f -print
Validate YAML files carefully before editing them.
Common causes include:
- Invalid YAML indentation
- Incorrect router names
- Incorrect internal container ports
- A missing Docker network
- DNS pointing to the wrong server
- Port 80 or 443 blocked upstream
- Invalid custom Traefik configuration
Dokploy’s troubleshooting documentation recommends using the Traefik logs to identify the exact dynamic configuration file containing an error.
-
Let’s Encrypt certificate issuance fails
Check DNS:
dig +short dokploy.example.com A
Check HTTP access:
curl -I http://dokploy.example.com
Check port 80:
ss -lntup | grep ':80\b'
Review Traefik logs:
docker logs --tail 300 dokploy-traefik
Common causes include:
- DNS has not propagated.
- The record points to the wrong IP.
- Port 80 is blocked.
- An
AAAArecord points to a nonfunctional IPv6 address. - Cloudflare proxy settings interfere with initial validation.
- The Let’s Encrypt rate limit has been reached.
- The hostname contains a typographical error.
Temporarily remove an incorrect
AAAArecord when IPv6 is not fully configured. -
Builds fail with DNS errors
Symptoms may include:
Could not resolve host: github.com
Or:
lookup ghcr.io: server misbehaving
Test container DNS:
See Also: How to Install Discourse on Ubuntu VPS
docker run --rm alpine nslookup github.com
Inspect Docker configuration:
cat /etc/docker/daemon.json
When the file does not exist, create:
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<'EOF' { "dns": [ "1.1.1.1", "8.8.8.8" ] } EOFValidate:
jq . /etc/docker/daemon.json
Restart Docker during a maintenance window:
systemctl restart docker
Retest:
docker run --rm alpine nslookup github.com
When
daemon.jsonalready contains settings, merge thednsproperty instead of replacing the file. Dokploy documents this correction for Docker build environments that cannot use the VPS provider’s default resolver. -
Docker reports that all predefined address pools are exhausted
The error may appear as:
all predefined address pools have been fully subnetted
Count Docker networks:
docker network ls | wc -l
Remove unused networks:
docker network prune -f
For a long-term fix, configure additional address pools in
/etc/docker/daemon.json.Example:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" }, "default-address-pools": [ { "base": "172.17.0.0/12", "size": 24 }, { "base": "10.100.0.0/16", "size": 24 } ] }Validate:
jq . /etc/docker/daemon.json
Restart Docker during a maintenance window:
systemctl restart docker
Verify:
docker info | grep -A 5 "Default Address Pools"
Choose ranges that do not overlap with the VPS network, VPNs, or private infrastructure. Dokploy documents expanded Docker address pools as the permanent fix for exhausted network allocations.
-
Services cannot communicate through Docker Swarm
Check whether the IPVS kernel module is available:
modprobe ip_vs lsmod | grep ip_vs
Inspect kernel configuration:
grep -E \ 'CONFIG_IP_VS|CONFIG_NETFILTER_XT_MATCH_IPVS|CONFIG_NETFILTER_XT_MARK' \ /boot/config-$(uname -r)
A standard Ubuntu VPS kernel should normally support the required Swarm networking features. Minimal or custom kernels may not.
When IPVS is unavailable and the kernel cannot be changed, install using DNS round-robin mode:
curl -fsSL https://dokploy.com/install.sh | \ sudo ENDPOINT_MODE=dnsrr shDNSRR has limitations, including different load-balancing behavior and restrictions on ingress-mode published ports. It should therefore be treated as a compatibility workaround rather than the default configuration.
-
Disk space is exhausted
Check usage:
df -h df -ih docker system df
Find large directories:
du -xhd1 /var/lib/docker 2>/dev/null | sort -h du -xhd1 /etc/dokploy 2>/dev/null | sort -h
Clean build cache:
docker builder prune
Remove unused images:
docker image prune -a
Remove unused containers and networks:
docker system prune
Use:
docker system prune -a
only after reviewing its impact.
See Also: 🚀 Deploy ERPNext on Ubuntu VPS
Do not delete Docker volumes manually from
/var/lib/docker. -
Dokploy does not return after a reboot
Check Docker:
systemctl status docker --no-pager
Start it if necessary:
systemctl enable --now docker
Check services:
docker service ls docker service ps dokploy docker service ps dokploy-postgres
Check logs:
docker service logs --tail 200 dokploy docker service logs --tail 200 dokploy-postgres docker logs --tail 200 dokploy-traefik
Restart Dokploy:
docker service scale dokploy=0 sleep 5 docker service scale dokploy=1
Restart Traefik:
docker restart dokploy-traefik
Avoid restarting the entire server repeatedly without first examining the logs.
Final production checklist
Before hosting production workloads, confirm all of the following:
[ ] Ubuntu is fully updated. [ ] The server has at least 2 GB RAM and 30 GB storage. [ ] Adequate production capacity has been allocated. [ ] Swap is configured on small VPS instances. [ ] Ports 80 and 443 are publicly reachable. [ ] SSH is restricted to trusted sources where practical. [ ] The Dokploy administrator account has been created. [ ] Two-factor authentication is enabled. [ ] The Dokploy panel uses a dedicated HTTPS hostname. [ ] Direct IP:3000 access has been removed. [ ] Port 3000 has been removed from external firewalls. [ ] Root password login is disabled. [ ] A non-root sudo administrator has been tested. [ ] Automatic security updates are enabled. [ ] Git credentials use least privilege. [ ] Databases are not publicly exposed unnecessarily. [ ] An S3-compatible backup destination is configured. [ ] Dokploy configuration backups are scheduled. [ ] Database backups are scheduled and tested. [ ] Persistent application volumes are backed up. [ ] A restoration test has been completed. [ ] Disk, memory, Docker usage, and service health are monitored. [ ] Docker log rotation is configured. [ ] Update and rollback procedures are documented.
Useful command reference
Service status
docker service ls docker ps docker node ls
Dokploy logs
docker service logs -f dokploy
PostgreSQL logs
docker service logs -f dokploy-postgres
Traefik logs
docker logs -f dokploy-traefik
Resource usage
docker stats docker system df free -h df -hT
Network inspection
ss -lntup docker network ls ip address ip route
Restart Dokploy
docker service scale dokploy=0 docker service scale dokploy=1
Restart Traefik
docker restart dokploy-traefik
Update Dokploy
curl -fsSL https://dokploy.com/install.sh | sh -s update
Remove direct port 3000 access
docker service update \
--publish-rm "published=3000,target=3000,mode=host" \
dokploy
Conclusion
You now know how to install Dokploy on Ubuntu VPS. Dokploy provides a convenient self-hosted deployment platform while retaining direct control over the underlying VPS, containers, applications, domains, and data.
A secure production deployment should not stop after running the installation script. The administrator should also:
See Also: 🚀 Deploy Virtualmin on AlmaLinux VPS (5 Minute Quick-Start Guide)
- Configure a dedicated HTTPS hostname
- Remove direct port 3000 exposure
- Harden SSH access
- Protect administrator accounts with multifactor authentication
- Restrict database ports
- Configure off-server backups
- Monitor storage and Docker resource consumption
- Review release notes and back up before upgrades
Once these controls are in place, the Ubuntu VPS is ready to host applications, databases, Docker Compose stacks, and automated Git-based deployments through Dokploy.









