Deploying Appsmith on Budget Hetzner Cloud VPS
What You’ll Need
- Hetzner VPS or DigitalOcean for cloud server hosting
- Namecheap for managing domain DNS records
- A Linux terminal or SSH client installed on your local machine
- Basic knowledge of Docker containers and reverse proxies
Table of Contents
- Provisioning Your Hetzner Cloud Server
- Server Hardening and Docker Environment Setup
- Deploying Appsmith with Docker Compose and Caddy
- Connecting Appsmith to External Workflows and Webhooks
- Automated Backups and Maintenance Scripts
- Getting Started
Provisioning Your Hetzner Cloud Server
Building internal tools used to require heavy frontend engineering or expensive managed platforms. Appsmith gives developers an open source low-code platform to build dashboards, admin panels, and database interfaces in minutes. While cloud-hosted options exist, self-hosting Appsmith gives you complete data ownership, unlimited internal users, and zero usage-based fees.
To start, sign up for a cloud account on Hetzner VPS. Hetzner offers high performance cloud servers located in North America and Europe at a fraction of the cost of legacy cloud providers. For hosting Appsmith along with an embedded database, select the CPX11 or CX22 instance tier. These tiers provide 2 vCPUs and 2GB to 4GB of RAM, which is ideal for hosting an internal application engine on a budget.
Navigate to the Cloud Console in Hetzner and click Create Server. Choose the location closest to your team or end users. Select Ubuntu 24.04 LTS as your operating system image. Under the Server Type selection, pick Shared vCPU and select CX22 or CPX11.
Before deploying the instance, add your public SSH key to the SSH keys tab. This ensures secure passwordless authentication. Assign a hostname such as appsmith-node-01 and launch the instance.
While the server provisions, jump over to your domain provider, such as Namecheap. Create an A Record in your DNS management console pointing your custom sub-domain (for example, app.yourdomain.com) to the public IPv4 address assigned to your new server.
💡 Fast-Track Your Project: Don’t want to configure this yourself? I build custom n8n pipelines and bots. Message me with code SYS3-HUGO.
Server Hardening and Docker Environment Setup
Once your server is online, log in using your terminal:
ssh root@your-server-ip
Appsmith utilizes an internal MongoDB database instance along with backend Java and Node.js microservices. Running these services requires stable memory headroom. Budget servers with 2GB or 4GB of RAM can experience out-of-memory errors during spikes. We will prevent system instability by creating a 4GB virtual swap file before installing software packages.
Run these commands to configure system swap, enable automatic kernel swapping, and update system packages:
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Next, configure the Uncomplicated Firewall (UFW) to block unauthorized incoming connections. We only allow SSH, HTTP, and HTTPS traffic:
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y curl git ufw fail2ban iptables ca-certificates gnupg lsb-release
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
Now install Docker Engine along with the Docker Compose plugin using the official Docker repository packages:
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -y
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable docker
sudo systemctl start docker
Verify that Docker is active and running:
sudo docker --version
sudo docker compose version
Deploying Appsmith with Docker Compose and Caddy
Running Appsmith directly exposed to port 80 or 443 can lead to port conflicts and SSL configuration headaches. We will run Appsmith inside Docker alongside Caddy Server. Caddy automates SSL certificate issuing and renewal via Let’s Encrypt while acting as an efficient reverse proxy.
Create a dedicated directory for your infrastructure configuration:
mkdir -p /opt/appsmith
cd /opt/appsmith
Create a production-ready docker-compose.yml file using your text editor:
nano /opt/appsmith/docker-compose.yml
Paste the following exact YAML configuration:
version: '3.8'
services:
appsmith:
image: appsmith/appsmith-ce:latest
container_name: appsmith
restart: unless-stopped
ports:
- "8080:80"
- "8443:443"
environment:
- APPSMITH_ENCRYPTION_PASSWORD=SuperSecretEncryptionKey123!
- APPSMITH_ENCRYPTION_SALT=SuperSecretSaltValue456!
- APPSMITH_DISABLE_TELEMETRY=true
volumes:
- ./stacks:/appsmith-stacks
networks:
- appsmith-net
caddy:
image: caddy:2.7.6-alpine
container_name: caddy_proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- appsmith
networks:
- appsmith-net
networks:
appsmith-net:
driver: bridge
volumes:
caddy_data:
caddy_config:
Now create the Caddyfile configuration inside /opt/appsmith/:
nano /opt/appsmith/Caddyfile
Insert the full reverse proxy configuration below. Replace app.yourdomain.com with the actual domain name configured in your DNS provider, and replace your-email@domain.com with your real email address:
app.yourdomain.com {
tls your-email@domain.com
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
X-XSS-Protection "1; mode=block"
}
reverse_proxy appsmith:80 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Start the containers in detached mode:
cd /opt/appsmith
sudo docker compose up -d
Monitor the container deployment logs to ensure initialization proceeds cleanly without errors:
sudo docker compose logs -f appsmith
Appsmith initializes MongoDB, applies initial database migrations, and boots its backend platform. This initialization process can take from two to three minutes on budget instances. Once you see initialization completed in the logs, open https://app.yourdomain.com in your web browser. You will be greeted by the Appsmith administrator creation screen.
Connecting Appsmith to External Workflows and Webhooks
Appsmith functions best as an operational command center. You can construct custom user interfaces to trigger API calls, process database records, and invoke external automation pipelines.
When building workflows that connect your Appsmith frontend to microservices, asynchronous task queues handle backend processing load cleanly. If your application triggers complex background tasks, explore our guide on Building Distributed Webhook Consumers with Redis Queues to handle heavy request volume without blocking your browser UI.
To build interactive forms in Appsmith that invoke webhooks reliably, you must prevent lost requests or rate limit issues. Review our strategies on Designing Resilient Webhook Endpoints with Redis Queues for best practices on structural retry handling and queuing architecture.
Additionally, if your Appsmith operational dashboard controls data collection tools, scrapers, or automation tasks, you can invoke backend scripts directly. Learn how to construct high-performance data workers in our tutorial on Building Production Web Scraping Pipelines With Python.
Here is an example JSObject configuration you can add inside your Appsmith application interface to safely post user actions to an external backend webhook endpoint with authorization headers:
export default {
triggerBackendTask: async () => {
const payload = {
action: "PROCESS_DATASET",
requestedBy: appsmith.user.email,
parameters: {
filterStatus: SelectStatus.selectedOptionValue,
recordLimit: Number(InputLimit.text)
}
};
try {
let response = await ApiTriggerTask.run(payload);
showAlert("Task successfully queued! Task ID: " + response.taskId, "success");
await storeValue("lastTaskId", response.taskId);
} catch (error) {
showAlert("Failed to trigger process: " + error.message, "error");
}
}
}
Automated Backups and Maintenance Scripts
Production deployments demand routine volume backups and log rotations. Since Appsmith stores application configurations, connection keys, and operational data within the /opt/appsmith/stacks directory, backing up this folder guarantees complete recovery capability.
Create a robust bash script that backs up your entire environment to a compressed archive:
mkdir -p /opt/appsmith/backups
nano /opt/appsmith/backup.sh
Paste the full backup script into the file:
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/opt/appsmith/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
ARCHIVE_NAME="appsmith_backup_${TIMESTAMP}.tar.gz"
echo "Starting Appsmith backup at $(date)..."
# Create target backup directory if absent
mkdir -p "${BACKUP_DIR}"
# Compress persistent stack volume
tar -czf "${BACKUP_DIR}/${ARCHIVE_NAME}" -C /opt/appsmith stacks
echo "Backup file created at ${BACKUP_DIR}/${ARCHIVE_NAME}"
# Delete backups older than 7 days
find "${BACKUP_DIR}" -type f -name "appsmith_backup_*.tar.gz" -mtime +7 -exec rm -f {} \;
echo "Backup maintenance complete."
Make the backup script executable:
chmod +x /opt/appsmith/backup.sh
Set up a system cron job to execute the backup automatically every night at 2:00 AM:
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/appsmith/backup.sh >> /var/log/appsmith_backup.log 2>&1") | crontab -
To update Appsmith to the newest version in the future, simply navigate to your configuration directory, pull the new container images, and restart the compose stack:
cd /opt/appsmith
sudo docker compose pull
sudo docker compose up -d --remove-orphans
Using this architecture on a server from Hetzner VPS backed by domain management from Namecheap, you gain a performant, enterprise-capable internal tool server running on minimal monthly operational expenditure.
Getting Started
Deploying low-code administrative interfaces on virtual private servers gives software development teams maximum flexibility without recurring per-user software subscriptions. By provisioning an instance on Hetzner VPS or DigitalOcean, pointing DNS records through Namecheap, and automating TLS certificates using Caddy, you keep full ownership over internal system access and underlying data security.
Outsource Your Automation
Don’t have time? I build production n8n workflows, WhatsApp bots, and fully automated YouTube Shorts pipelines. Hire me on Fiverr, mention SYS3-HUGO for priority. Or DM at chasebot.online.
Want to automate this yourself?
Start with n8n Cloud (free tier available) or self-host on a Hetzner VPS for full control.
Want this engine running on your own VPS?
This blog publishes itself — daily, unattended, on free API tiers. The full engine, Hugo theme, and setup guide are available as System 3.
Get System 3