Deployment & Security Guide for VPS Installation
This comprehensive guide covers deploying InsForge on a generic VPS (Virtual Private Server) for production, hardening your instance with security best practices, and maintaining it over time with safe updates and rollback procedures.Scope: This guide is provider-agnostic. It works on any Linux VPS β Ubuntu/Debian recommended β from providers such as DigitalOcean, Hetzner, Linode, Vultr, OVH, or a bare-metal server. For cloud-specific guides (AWS EC2, GCP, Azure, Render), see the deployment directory.
π Table of Contents
- Prerequisites
- Part 1 β Deployment
- Part 2 β Security
- Part 3 β Updating & Maintenance
- Quick Reference
- Troubleshooting
Prerequisites
Before starting, ensure you have:- A VPS running Ubuntu 22.04 LTS or Ubuntu 24.04 LTS (Debian 12 also works)
- Root or sudo access to the server
- A registered domain name (recommended for production)
- Basic familiarity with the Linux command line and SSH
Part 1 β Deployment
1. Server Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 2 GB | 4 GB+ |
| Storage | 20 GB SSD | 40 GB+ SSD |
| OS | Ubuntu 22.04+ | Ubuntu 24.04 LTS |
| Network | Public IPv4 | Public IPv4 + IPv6 |
π‘ Tip: For production workloads with multiple users, start with 4 GB RAM. Monitor usage with docker stats and scale vertically as needed.
InsForge consists of 4 services that run together:
| Service | Description | Internal Port |
|---|---|---|
| PostgreSQL | Primary database | 5432 |
| PostgREST | Auto-generated REST API layer | 3000 (mapped to 5430) |
| InsForge | Node.js backend + dashboard | 7130, 7131 |
| Deno | Serverless functions runtime | 7133 |
2. Initial Server Setup
2.1 Connect to Your VPS
2.2 Update System Packages
2.3 Create a Deploy User (Non-Root)
Never run production services as root. Create a dedicated user:2.4 Set the Timezone
2.5 Enable Automatic Security Updates
3. Install Docker & Docker Compose
3.1 Install Docker Engine
3.2 Add Deploy User to the Docker Group
3.3 Verify Docker Installation
β οΈ Security Note: Adding a user to the docker group grants root-equivalent privileges on the host. This is acceptable for a dedicated deploy user but should not be done for general-purpose accounts on shared servers.
4. Deploy InsForge with Docker Compose
4.1 Download the Production Docker Compose File
4.2 Start InsForge
4.3 Verify All Services Are Running
running or healthy state:
4.4 Test the Health Endpoint
5. Environment Variable Configuration
Edit your.env file to configure InsForge for production:
5.1 Required Variables
These must be changed from defaults before going to production:β οΈ Important:JWT_SECRETandENCRYPTION_KEYshould be different values. IfENCRYPTION_KEYis not set, InsForge falls back toJWT_SECRETβ but rotatingJWT_SECRETlater will permanently corrupt all stored secrets (API keys, OAuth tokens, etc.).
5.2 Database Variables
5.3 Port Variables
Default ports used by InsForge:π‘ You can change these if they conflict with other services on your VPS.
5.4 Required for Deployments
These variables are only needed if you plan to use InsForgeβs deployment features (deploying projects via the dashboard). If you donβt need deployments, skip this section.5.5 Optional Variables
6. Reverse Proxy Setup
A reverse proxy sits in front of InsForge, providing TLS termination, HTTP/2, and a clean URL without port numbers.Option A: Nginx (Recommended)
6.1 Install Nginx
6.2 Create the Site Configuration
insforge.yourdomain.com with your actual domain:
6.3 Enable the Site
Option B: Caddy (Automatic HTTPS)
Caddy is a simpler alternative that handles TLS certificates automatically.Install Caddy
Configure Caddy
7. HTTPS / TLS Setup
If you chose Caddy in Step 6, TLS is already handled automatically. Skip to Part 2.
7.1 Install Certbot (for Nginx)
7.2 Obtain SSL Certificates
- Verify domain ownership via HTTP challenge
- Obtain a signed certificate from Letβs Encrypt
- Automatically update your Nginx configuration to serve HTTPS
- Set up HTTP β HTTPS redirect
7.3 Verify Auto-Renewal
Letβs Encrypt certificates expire every 90 days. Certbot installs a systemd timer for automatic renewal:7.4 Update InsForge Environment for HTTPS
After obtaining your certificate, update your.env to use HTTPS URLs:
Part 2 β Security
8. Port Management
Ports That Should Be Open (via Reverse Proxy)
| Port | Protocol | Purpose |
|---|---|---|
| 22 | TCP | SSH (restrict source IP) |
| 80 | TCP | HTTP β HTTPS redirect |
| 443 | TCP | HTTPS (reverse proxy) |
Ports That Should Be Closed to the Public
These ports are used only for internal Docker service-to-service communication. They should never be exposed to the internet:| Port | Service | Why Close It |
|---|---|---|
| 5432 | PostgreSQL | Direct DB access β use docker exec instead |
| 5430 | PostgREST | Internal REST layer β proxied through InsForge |
| 7130 | InsForge | Accessed via reverse proxy on 443, not directly |
| 7131 | Auth | Internal auth service |
| 7133 | Deno | Internal serverless runtime |
β οΈ Critical: The defaultdocker-compose.ymlbinds ports to0.0.0.0(all interfaces), not127.0.0.1. This means Docker will expose services directly to the internet, bypassing UFW entirely (Docker manipulates iptables directly). You MUST add the127.0.0.1:prefix to every published port in yourdocker-compose.yml:Without this prefix, anyone on the internet can reach these services directly β including PostgreSQL with default credentials. See Section 9.2 for details.
9. Firewall Setup (UFW)
UFW (Uncomplicated Firewall) is the simplest way to manage iptables on Ubuntu.9.1 Install and Configure UFW
β οΈ Critical: Always allow SSH before enabling UFW, or you will lock yourself out of the server.
9.2 Docker and UFW Caveat
Docker manipulates iptables directly, which can bypass UFW rules. To prevent this: Option 1 β Bind ports to localhost (recommended): In yourdocker-compose.yml, prefix ports with 127.0.0.1::
β οΈ Disabling Docker iptables requires manual network configuration. Option 1 is preferred for most setups.
9.3 Restrict SSH to Your IP (Optional)
For maximum security, restrict SSH access to a known IP address:10. Run Services as a Non-Root User
InsForgeβs Docker image already follows non-root best practices:- The production Dockerfile sets
USER node(UID 1000), so the application process inside the container runs as a non-root user. - System-level Docker operations are managed by the
deployuser (created in Step 2.3), which has access to the Docker socket via thedockergroup.
security_opt to each service in your docker-compose.yml to prevent privilege escalation:
11. SSH Hardening
11.1 Use SSH Key Authentication
11.2 Disable Password Authentication
Once key-based auth is confirmed working:11.3 Install Fail2Ban
Fail2Ban automatically bans IPs that show malicious activity (e.g., brute-force SSH):12. Docker Security
12.1 Keep Docker Updated
12.2 Limit Container Resources (Optional)
Prevent a single container from consuming all resources:12.3 Read-Only Root Filesystem (Advanced)
For extra hardening, mount the container filesystem as read-only where possible:β οΈ This requires testing β some services need writable directories for caches or temporary files.
13. Secrets Management
Do β
- Store secrets in the
.envfile withchmod 600 ~/insforge/.env - Use separate values for
JWT_SECRETandENCRYPTION_KEY - Generate secrets with
openssl rand -base64 32 - Back up your
.envfile to a secure, offline location
Donβt β
- Commit
.envto version control - Reuse the same secret for multiple variables
- Use default passwords (
change-this-password,postgres) in production - Share secrets over unencrypted channels
Part 3 β Updating & Maintenance
14. Pre-Update Backup
Always back up before updating. This gives you a recovery path if anything goes wrong.14.1 Back Up the Database
14.2 Back Up Environment and Volumes
14.3 Record Current Version
15. Updating InsForge
15.1 Pull the Latest Images
15.2 Apply the Update
Ctrl+C to stop following logs.
15.3 Verify the Update
15.4 Update the Docker Compose File (If Needed)
Occasionally, new releases may include changes todocker-compose.yml. To pick up these changes:
16. Rollback Procedure
If an update causes issues, follow these steps to revert:16.1 Stop the Broken Services
16.2 Restore the Previous Docker Compose File
16.3 Pin to a Specific Image Version
Editdocker-compose.yml and replace latest tags with the previous version:
16.4 Restore the Database (If Needed)
Only restore the database if the update included a database migration that caused issues:16.5 Restore Environment File (If Changed)
17. Automated Backups
Set up a cron job for daily automated backups:17.1 Create a Backup Script
17.2 Schedule with Cron
17.3 Off-Site Backups (Recommended)
For disaster recovery, copy backups to an external location:18. Monitoring & Health Checks
18.1 Check Service Status
18.2 View Logs
18.3 Health Check Endpoint
Monitor the health endpoint externally. A simple cron-based check:https://insforge.yourdomain.com/api/health.
Quick Reference
Essential Commands
Security Checklist
- Deploy user created (non-root)
- SSH key authentication enabled
- SSH password authentication disabled
- Root login disabled
- UFW firewall enabled (ports 22, 80, 443 only)
- Docker ports bound to
127.0.0.1 - Fail2Ban installed and active
-
JWT_SECRETchanged from default (32+ chars) -
ENCRYPTION_KEYset (separate fromJWT_SECRET) -
ADMIN_PASSWORDchanged from default -
POSTGRES_PASSWORDchanged from default -
.envfile permissions set to600 - HTTPS enabled via Certbot or Caddy
- Automated daily backups configured
- Unattended security updates enabled
Troubleshooting
Cannot Connect After Enabling UFW
If youβre locked out, use your VPS providerβs web console (out-of-band access) to:Docker Bypasses UFW
Docker directly manipulates iptables. Bind ports to127.0.0.1 in docker-compose.yml as described in Section 9.2.
Services Fail to Start
SSL Certificate Wonβt Renew
Port Conflicts
Database Connection Issues
π Need Help?
- Documentation: https://docs.insforge.dev
- Discord Community: https://discord.com/invite/MPxwj5xVvW
- GitHub Issues: https://github.com/insforge/insforge/issues