Tools
Tools: Self-hosting DocuSeal on a Hetzner Ubuntu Server
2026-01-16
0 views
admin
Prerequisites ## Step 0: Create a Server on Hetzner ## Step 1: Update Your Server ## Step 2: Install and Configure UFW Firewall ## Step 3: Docker Installation ## Step 4: Installing Caddy for Automatic HTTPS ## Step 5: Running DocuSeal with Docker Compose ## Step 6: Access Your DocuSeal Instance ## Optional Configurations ## Security Recommendations ## Cost Comparison with SaaS Alternatives ## Comparison with Managed Hosting Want to sign documents using DocuSeal but prefer to fully control your infrastructure? By self-hosting DocuSeal on a Linux Ubuntu server, you can cut down costs, keep your sensitive documents private, and avoid per-signature fees! Looking for something simpler? Deploy in 25 seconds Before we start, make sure you have: Log into your Hetzner Cloud Console and click Create Resource. Choose Shared Resources > Cost-Optimized. The CX23 server (2 vCPU, 4GB RAM) is perfect at just €2.99/month. Select a location close to your users and Ubuntu 24.04 as the operating system. Add your SSH public key: Give your server a name and click Create & Buy now. Once created, copy the IP address and connect: Verify with sudo ufw status verbose. Note: Docker can sometimes ignore UFW rules. See this guide for extra settings. Setup dependencies and Docker's GPG key: Add Docker repository: Install Docker Engine: Verify with sudo docker run hello-world. Caddy handles SSL certificates automatically from Let's Encrypt. Important: Point your domain's A record (IPv4) and AAAA record (IPv6) to your server's IP before this step. Replace contents with: Restart Caddy: sudo systemctl restart caddy Create a directory and compose file: Visit your domain in any web browser. Follow the setup steps to create your admin account. 🎉 Congratulations! You now have your own self-hosted DocuSeal instance! Restart: sudo docker compose down && sudo docker compose up -d *Railway charges for actual usage. With self-hosting on Hetzner, you get similar specs for ~€3/month, but you handle all setup and maintenance. See the full tutorial with screenshots on Sliplane.io If managing your own server is too much, check out how easy it is to deploy DocuSeal on Sliplane in just 25 seconds! Happy self-hosting! 🚀 Templates let you quickly answer FAQs or store snippets for re-use. TIL there is compliance standards for electronic signing lol thank you for the detailed tutorial!! Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse COMMAND_BLOCK:
# On macOS
pbcopy < ~/.ssh/id_ed25519.pub # On Linux
cat ~/.ssh/id_ed25519.pub Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
# On macOS
pbcopy < ~/.ssh/id_ed25519.pub # On Linux
cat ~/.ssh/id_ed25519.pub COMMAND_BLOCK:
# On macOS
pbcopy < ~/.ssh/id_ed25519.pub # On Linux
cat ~/.ssh/id_ed25519.pub COMMAND_BLOCK:
ssh root@YOUR_SERVER_IP Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
ssh root@YOUR_SERVER_IP COMMAND_BLOCK:
ssh root@YOUR_SERVER_IP COMMAND_BLOCK:
sudo apt-get update
sudo apt-get upgrade -y Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo apt-get update
sudo apt-get upgrade -y COMMAND_BLOCK:
sudo apt-get update
sudo apt-get upgrade -y COMMAND_BLOCK:
sudo apt install ufw -y
sudo ufw allow 22 # SSH
sudo ufw allow 80 # HTTP
sudo ufw allow 443 # HTTPS
sudo ufw enable Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo apt install ufw -y
sudo ufw allow 22 # SSH
sudo ufw allow 80 # HTTP
sudo ufw allow 443 # HTTPS
sudo ufw enable COMMAND_BLOCK:
sudo apt install ufw -y
sudo ufw allow 22 # SSH
sudo ufw allow 80 # HTTP
sudo ufw allow 443 # HTTPS
sudo ufw enable COMMAND_BLOCK:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg COMMAND_BLOCK:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg COMMAND_BLOCK:
echo \ "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
echo \ "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update COMMAND_BLOCK:
echo \ "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update COMMAND_BLOCK:
sudo apt-get install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin -y Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo apt-get install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin -y COMMAND_BLOCK:
sudo apt-get install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin -y COMMAND_BLOCK:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update
sudo apt install caddy -y Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update
sudo apt install caddy -y COMMAND_BLOCK:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update
sudo apt install caddy -y COMMAND_BLOCK:
sudo nano /etc/caddy/Caddyfile Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo nano /etc/caddy/Caddyfile COMMAND_BLOCK:
sudo nano /etc/caddy/Caddyfile CODE_BLOCK:
yourdomain.com { reverse_proxy localhost:3000
} Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
yourdomain.com { reverse_proxy localhost:3000
} CODE_BLOCK:
yourdomain.com { reverse_proxy localhost:3000
} CODE_BLOCK:
mkdir ~/docuseal
cd ~/docuseal
nano compose.yml Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
mkdir ~/docuseal
cd ~/docuseal
nano compose.yml CODE_BLOCK:
mkdir ~/docuseal
cd ~/docuseal
nano compose.yml CODE_BLOCK:
services: docuseal: image: docuseal/docuseal:2.2.9 restart: always ports: - "3000:3000" volumes: - docuseal_data:/data volumes: docuseal_data: Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
services: docuseal: image: docuseal/docuseal:2.2.9 restart: always ports: - "3000:3000" volumes: - docuseal_data:/data volumes: docuseal_data: CODE_BLOCK:
services: docuseal: image: docuseal/docuseal:2.2.9 restart: always ports: - "3000:3000" volumes: - docuseal_data:/data volumes: docuseal_data: COMMAND_BLOCK:
sudo docker compose up -d Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
sudo docker compose up -d COMMAND_BLOCK:
sudo docker compose up -d CODE_BLOCK:
services: docuseal: image: docuseal/docuseal:2.2.9 restart: always depends_on: - postgres ports: - "3000:3000" volumes: - docuseal_data:/data environment: - DATABASE_URL=postgres://docuseal:your_secure_password@postgres:5432/docuseal postgres: image: postgres:16 restart: always volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_USER=docuseal - POSTGRES_PASSWORD=your_secure_password - POSTGRES_DB=docuseal volumes: docuseal_data: postgres_data: Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
services: docuseal: image: docuseal/docuseal:2.2.9 restart: always depends_on: - postgres ports: - "3000:3000" volumes: - docuseal_data:/data environment: - DATABASE_URL=postgres://docuseal:your_secure_password@postgres:5432/docuseal postgres: image: postgres:16 restart: always volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_USER=docuseal - POSTGRES_PASSWORD=your_secure_password - POSTGRES_DB=docuseal volumes: docuseal_data: postgres_data: CODE_BLOCK:
services: docuseal: image: docuseal/docuseal:2.2.9 restart: always depends_on: - postgres ports: - "3000:3000" volumes: - docuseal_data:/data environment: - DATABASE_URL=postgres://docuseal:your_secure_password@postgres:5432/docuseal postgres: image: postgres:16 restart: always volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_USER=docuseal - POSTGRES_PASSWORD=your_secure_password - POSTGRES_DB=docuseal volumes: docuseal_data: postgres_data: CODE_BLOCK:
environment: - SMTP_ADDRESS=smtp.example.com - SMTP_PORT=587 - [email protected] - SMTP_PASSWORD=your-password - SMTP_DOMAIN=your-domain.com Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
environment: - SMTP_ADDRESS=smtp.example.com - SMTP_PORT=587 - [email protected] - SMTP_PASSWORD=your-password - SMTP_DOMAIN=your-domain.com CODE_BLOCK:
environment: - SMTP_ADDRESS=smtp.example.com - SMTP_PORT=587 - [email protected] - SMTP_PASSWORD=your-password - SMTP_DOMAIN=your-domain.com CODE_BLOCK:
cd ~/docuseal
sudo docker compose pull
sudo docker compose up -d Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
cd ~/docuseal
sudo docker compose pull
sudo docker compose up -d CODE_BLOCK:
cd ~/docuseal
sudo docker compose pull
sudo docker compose up -d - A Hetzner account (or any other cloud provider)
- Basic SSH experience
- An SSH key pair on your local machine - Check for new versions on DocuSeal's DockerHub
- Update the image tag in compose.yml - Regularly apply updates and security patches
- Set strong passwords and control user access
- Monitor server logs for suspicious activity
- Install Fail2ban for extra security
- Keep Docker images updated
- Set up regular backups of your /data volume - Location Germany
- Education Karlsruher Institute for Technology
- Pronouns he/him
- Work Co-Founder @ sliplane.io
- Joined Aug 31, 2020 - Joined Aug 17, 2023
how-totutorialguidedev.toaimllinuxubuntudebianserverfirewallpostgresqldockerssldatabase