> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arct.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Host Dokploy on a VPS

> Install Dokploy on an Arct Cloud Linux VPS with a secure HTTPS panel, persistent data, backups, and safe updates.

Arct Cloud provides an unmanaged Linux VPS. Dokploy is not preinstalled or managed by Arct Cloud; you are responsible for the Dokploy control plane, Docker Swarm, deployed workloads, security, backups, and updates.

This guide installs Dokploy on a fresh Ubuntu 24.04 server using Dokploy's official stable installation script. Ubuntu 24.04 LTS is listed as a tested distribution by Dokploy.

## Requirements

| Basis                             |                          CPU |  RAM |                  Storage |
| --------------------------------- | ---------------------------: | ---: | -----------------------: |
| **Official Dokploy minimum**      | No numeric minimum published | 2 GB |                    30 GB |
| **Practical Arct recommendation** |                      2 vCPUs | 4 GB | 40 GB NVMe (`cvm.micro`) |

The official minimum accounts for Docker build overhead. Use more CPU, RAM, and storage for concurrent builds, several databases, large images, or high-traffic services. A 4-vCPU, 8-GB RAM server (`cvm.small`) is a more practical starting point for multiple production workloads.

<Warning>Use a fresh server when possible. Dokploy requires ports `80`, `443`, and `3000` to be free during installation and initializes Docker Swarm.</Warning>

## Install Dokploy

<Steps>
  <Step title="Deploy Ubuntu 24.04">
    [Deploy a server](/compute/virtual-machines/deploy), select a plan for the control plane plus your applications, and choose Ubuntu 24.04.
  </Step>

  <Step title="Connect over SSH">
    Find the server IP address in the Arct Cloud console, then connect:

    ```bash theme={null}
    ssh ubuntu@YOUR_SERVER_IP
    ```

    See [Connect via SSH](/compute/virtual-machines/connect-ssh) for key and username help.
  </Step>

  <Step title="Prepare DNS and a protected bootstrap path">
    Create an `A` record such as `dokploy.example.com` that points to the server's public IPv4 address. Add an `AAAA` record only when IPv6 is configured and reachable.

    Dokploy requires these TCP ports to be available:

    |   Port | Purpose                                                |
    | -----: | ------------------------------------------------------ |
    |   `22` | SSH administration                                     |
    |   `80` | Traefik HTTP traffic and certificate issuance          |
    |  `443` | Traefik HTTPS traffic                                  |
    | `3000` | Direct Dokploy panel access during setup; keep private |

    Check listeners and DNS before installing:

    ```bash theme={null}
    sudo ss -lntp
    getent ahostsv4 dokploy.example.com
    ```

    The installer fails if another process already uses `80`, `443`, or `3000`. A port can be free for Dokploy to bind without being reachable from the internet.

    Before running the installer, attach a network-level firewall or ACL in front of the VPS with this inbound policy:

    | Ports                   | Source during bootstrap                                 |
    | ----------------------- | ------------------------------------------------------- |
    | `22/tcp`                | Your current public admin IP only                       |
    | `80/tcp`, `443/tcp`     | Any, for Traefik and certificate issuance               |
    | `3000/tcp`              | Deny from the public internet                           |
    | All other inbound ports | Deny unless a deployed workload explicitly requires one |

    Attach and verify the policy before installation. Docker and Swarm published ports can bypass ordinary UFW rules. If no upstream firewall is available, preinstall Docker and establish a `DOCKER-USER` policy by following Docker's [official packet-filtering guidance](https://docs.docker.com/engine/network/packet-filtering-firewalls/) before running the Dokploy installer; a plain UFW deny rule is not a safe bootstrap boundary.
  </Step>

  <Step title="Run the official stable installer">
    Become root and run Dokploy's documented installation command. The installer selects the latest stable release and installs Docker when it is absent.

    ```bash theme={null}
    sudo -i
    curl -sSL https://dokploy.com/install.sh | sh
    exit
    ```

    Do not select the `canary` channel for a production control plane. If the script cannot detect the correct address on a multi-interface server, use Dokploy's documented `ADVERTISE_ADDR` option rather than reinitializing Swarm manually.
  </Step>

  <Step title="Create the administrator">
    From your local computer, create an SSH tunnel and leave it running:

    ```bash theme={null}
    ssh -L 3000:127.0.0.1:3000 ubuntu@YOUR_SERVER_IP
    ```

    Confirm that `http://YOUR_SERVER_IP:3000` is unreachable without the tunnel, then open `http://127.0.0.1:3000` through the tunnel. Complete the administrator setup with a long, unique password and enable two-factor authentication from the account settings.

    Do not continue if port `3000` is reachable directly from a non-allowlisted network. Do not connect Git providers, registries, or production secrets until the panel is protected with HTTPS.
  </Step>

  <Step title="Configure the panel domain and HTTPS">
    Confirm `dokploy.example.com` resolves to this VPS. In the Dokploy panel's domain settings, create the panel domain with:

    | Field          | Value                 |
    | -------------- | --------------------- |
    | Host           | `dokploy.example.com` |
    | Path           | `/`                   |
    | Container port | `3000`                |
    | HTTPS          | On                    |
    | Certificate    | Let's Encrypt         |

    Wait for Traefik to issue the certificate, then verify login at `https://dokploy.example.com`.
  </Step>

  <Step title="Remove direct access to port 3000">
    Only after the HTTPS panel works, remove the public IP-and-port publication recommended by Dokploy:

    ```bash theme={null}
    sudo docker service update \
      --publish-rm "published=3000,target=3000,mode=host" dokploy
    ```

    Keep ports `80` and `443` public for Traefik and certificate renewal, keep the upstream firewall deny for port `3000`, and close the SSH tunnel. Restrict SSH to trusted addresses where possible.
  </Step>

  <Step title="Verify the installation">
    Confirm the Swarm services, proxy, and public endpoint are healthy:

    ```bash theme={null}
    sudo docker service ls
    sudo docker service ps dokploy --no-trunc
    sudo docker ps --filter name=dokploy-traefik \
      --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
    curl -I https://dokploy.example.com
    ```

    Deploy a small test application, attach a test domain, and confirm HTTPS routing and logs work before adding production data.
  </Step>
</Steps>

## Persistent Data, Secrets, and Firewall Safety

Dokploy's control-plane state includes its internal PostgreSQL database and files under `/etc/dokploy`. The official control-plane backup combines both. Do not remove the Dokploy Docker volumes, Docker secrets, Swarm state, or `/etc/dokploy` during routine maintenance.

| Data                                   | Backup method                                                                               |
| -------------------------------------- | ------------------------------------------------------------------------------------------- |
| Dokploy database and `/etc/dokploy`    | **Web Server > Backups** to an S3-compatible destination                                    |
| Application databases                  | Each database's **Backup** tab and tested S3 restore                                        |
| Docker named volumes                   | Dokploy **Volume Backups** to S3; stop the writing container for the safest consistent copy |
| Bind mounts and host files             | Separate filesystem backup; Dokploy volume backups cover named volumes, not bind mounts     |
| Registry, Git, and application secrets | Included in control-plane state; protect backups and use least-privilege tokens             |

Prefer Dokploy's domain routing through Traefik instead of direct **Advanced > Ports** mappings. A domain's container-port field routes internally and does not publish that port on the host. When a database or service must be externally reachable, allow only the exact source IPs or place it behind a VPN.

<Warning>Dokploy manages Docker Swarm and can deploy privileged workloads. A compromised administrator or Git/registry credential can affect every service on the server. Limit panel access, rotate tokens, and grant repository access only where needed.</Warning>

## Back Up and Restore

Configure and test all three recovery layers:

1. Add an S3-compatible destination in Dokploy.
2. Open **Web Server > Backups**, create a scheduled control-plane backup, run one immediately, and confirm the `.zip` object exists remotely. It contains the Dokploy PostgreSQL database and `/etc/dokploy`.
3. Schedule backups for every managed database and test each backup job.
4. Configure volume backups for named volumes. Enable **Turn off Container** when the application writes to the volume and consistency matters.
5. Keep a record of the running Dokploy release with each recovery checkpoint.

To restore the control plane, open **Web Server > Backups > Restore Backup**, select the S3 destination and backup, review the destructive restore summary, and start the restore. Dokploy replaces the current `/etc/dokploy` content and internal database; you may need to sign in again and restart Traefik afterward.

If the server IP changed, update it in **Web Server > Server**, update DNS, and reconfigure IP-based Git provider callbacks. Restore application databases and volumes separately because they are not part of the control-plane archive.

<Note>Test recovery on a separate VPS. A backup is not verified until you can sign in, see projects, deploy, resolve domains, and restore representative database and volume data.</Note>

## Update and Roll Back Safely

Before an update:

1. Run and verify a control-plane backup plus all application database and volume backups.
2. Review the [Dokploy releases](https://github.com/Dokploy/dokploy/releases) for breaking changes.
3. Let active builds and deployments finish.
4. Record the current service image:

   ```bash theme={null}
   sudo docker service inspect dokploy \
     --format '{{.Spec.TaskTemplate.ContainerSpec.Image}}'
   ```

Update to the latest stable release with Dokploy's official command:

```bash theme={null}
sudo -i
curl -sSL https://dokploy.com/install.sh | sh -s update
exit
```

Verify panel login, Swarm services, Traefik, domains, and a representative deployment before cleaning up old images. Dokploy intentionally does not update Traefik automatically; do not replace Traefik independently without checking Dokploy compatibility and Traefik breaking changes.

The installer can target an exact official Dokploy version when recovery requires it:

```bash theme={null}
sudo -i
export DOKPLOY_VERSION=REPLACE_WITH_PREVIOUS_RELEASE
curl -sSL https://dokploy.com/install.sh | sh -s update
exit
```

Use a version copied from Dokploy's releases page. If an older control-plane image is incompatible with database changes, restore the full pre-update control-plane backup rather than repeatedly changing versions. Application rollback is separate: configure health checks for Swarm automatic rollback or a registry for deployment-level image rollback.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The installer reports that a required port is already in use">
    Run `sudo ss -lntp | grep -E ':(80|443|3000) '` and stop or move the conflicting service. Dokploy's Traefik must own ports `80` and `443`; do not install a second host reverse proxy on those ports.
  </Accordion>

  <Accordion title="The panel domain returns 404 or has no certificate">
    Confirm DNS points to this VPS before creating the domain, ports `80` and `443` are reachable, HTTPS is enabled, and Let's Encrypt is selected. Check the Dokploy Traefik logs for routing or ACME errors.
  </Accordion>

  <Accordion title="The panel became unreachable after port 3000 was removed">
    Use SSH or the Arct Cloud VNC console to restore the port publication while keeping the upstream firewall deny in place:

    ```bash theme={null}
    sudo docker service update \
      --publish-add "published=3000,target=3000,mode=host" dokploy
    ```

    Access it through the SSH tunnel, fix and verify the HTTPS route, then remove the publication again. Never reopen the bootstrap installer port to the public internet.
  </Accordion>

  <Accordion title="A Dokploy service is stuck or repeatedly rejected">
    Inspect `sudo docker service ps SERVICE_NAME --no-trunc`, `sudo docker service logs SERVICE_NAME --tail 100`, and `sudo docker node ls`. Address the first Swarm error rather than deleting volumes or reinitializing the cluster.
  </Accordion>

  <Accordion title="Builds freeze the server or fail unexpectedly">
    Check `free -h`, `df -h`, `sudo docker system df`, and service logs. Increase RAM or storage, reduce concurrent builds, or move builds off the control-plane host. Never prune named volumes as a generic disk-space fix.
  </Accordion>
</AccordionGroup>

## Official Resources

<CardGroup cols={3}>
  <Card title="Dokploy Installation" icon="book-open" href="https://docs.dokploy.com/docs/core/installation">
    Official requirements, supported distributions, ports, and installer.
  </Card>

  <Card title="Dokploy on GitHub" icon="github" href="https://github.com/Dokploy/dokploy">
    Source code, security policy, and issue tracker.
  </Card>

  <Card title="Dokploy Releases" icon="tag" href="https://github.com/Dokploy/dokploy/releases">
    Stable releases, fixes, and upgrade notes.
  </Card>
</CardGroup>

<Note>Dokploy is developed by the Dokploy project. Arct Cloud is an independent infrastructure provider and is not affiliated with, sponsored by, or endorsed by Dokploy.</Note>
