Skip to content

Deployment

Launch Formlander locally or on a server with environment-driven configuration.

One command installs everything on a fresh Ubuntu/Debian server:

Terminal window
curl -fsSL https://raw.githubusercontent.com/karloscodes/formlander/main/install.sh | sudo bash

The installer:

  • Prompts for your domain and email
  • Installs Docker and SQLite if needed
  • Deploys Formlander with SSL via Caddy
  • Sets up automatic daily updates at 3 AM

After installation, visit https://your-domain.com to log in.


Formlander is a self-contained Go binary. Configuration is powered by Viper, giving you flexible options:

  • Environment variables (prefix: FORMLANDER_) - highest priority
  • .env file - for easier local development
  • Environment variables always override .env file values

SQLite stores submissions and configuration in the storage/ directory by default.

Current status: Formlander v1.0.0 is now available as an open-source project. Pull the Docker image from Docker Hub or download binaries from GitHub Releases.

For production deployments, you must set this security variable:

Terminal window
FORMLANDER_SESSION_SECRET=your-secret-here # Generate with: openssl rand -hex 32

⚠️ Important: Required in production. In development/test, a fixed default secret is used (sessions persist across restarts).

Common configuration options:

Terminal window
FORMLANDER_ENV=production # Environment: development, production (default: development)
FORMLANDER_PORT=8080 # HTTP port (default: 8080)
FORMLANDER_SESSION_SECRET=your-secret # HMAC secret (REQUIRED in production)
FORMLANDER_LOG_LEVEL=info # Log level: debug, info, warn, error (default: info)
FORMLANDER_DATA_DIR=./storage # Data directory (default: ./storage)

Create a .env file in your project root for easier local development:

Terminal window
# Required in production
FORMLANDER_SESSION_SECRET=your-secret-here
# Optional overrides
FORMLANDER_ENV=production
FORMLANDER_PORT=8080
FORMLANDER_LOG_LEVEL=info
FORMLANDER_DATA_DIR=./storage

Configuration precedence: Environment variables always override .env file values. This is useful for keeping secrets in environment variables while maintaining other settings in the .env file.

Environment VariableDefaultDescription
FORMLANDER_SESSION_SECRET(required in production)HMAC secret (fixed default in dev/test)
FORMLANDER_ENVproductionEnvironment: development, production
FORMLANDER_PORT8080HTTP server port
FORMLANDER_LOG_LEVELerrorLog level: debug, info, warn, error
FORMLANDER_DATA_DIRstorageBase directory for data files

For a complete list of advanced configuration options, see the Formlander GitHub repository.

First-time setup: After starting Formlander for the first time, visit the web interface at http://localhost:8080 with default credentials:

You’ll be required to change the password on first login.

Terminal window
docker run -d \
-p 8080:8080 \
-e FORMLANDER_SESSION_SECRET=$(openssl rand -hex 32) \
-v $(pwd)/storage:/app/storage \
karloscodes/formlander:latest

Then visit http://localhost:8080 to log in with default credentials.

You can use a .env file with Docker for easier configuration management.

Create a .env file:

Terminal window
# Required in production
FORMLANDER_SESSION_SECRET=your-secret-here
# Optional overrides
FORMLANDER_ENV=production
FORMLANDER_PORT=8080
FORMLANDER_LOG_LEVEL=info

Run with .env file:

Terminal window
docker run -d \
--env-file .env \
-p 8080:8080 \
-v $(pwd)/storage:/app/storage \
karloscodes/formlander:latest

Or mix both (environment variables override .env file):

This is useful for keeping secrets in environment variables while maintaining other settings in the .env file:

Terminal window
docker run -d \
-e FORMLANDER_SESSION_SECRET=$(openssl rand -hex 32) \
--env-file .env \
-p 8080:8080 \
-v $(pwd)/storage:/app/storage \
karloscodes/formlander:latest

Formlander images are published for both AMD64 and ARM64 architectures on each release:

Terminal window
# Latest stable release (multi-arch manifest)
docker pull karloscodes/formlander:latest
# Architecture-specific latest tags
docker pull karloscodes/formlander:latest-amd64
docker pull karloscodes/formlander:latest-arm64
# Specific version (multi-arch manifest)
docker pull karloscodes/formlander:v1.0.0
# Architecture-specific version tags
docker pull karloscodes/formlander:v1.0.0-amd64
docker pull karloscodes/formlander:v1.0.0-arm64

Note: Docker will automatically pull the correct architecture for your system when using the multi-arch tags (latest or version without suffix).

  1. Download the latest release from GitHub Releases
  2. Extract and set required environment variables:
    Terminal window
    export FORMLANDER_SESSION_SECRET=$(openssl rand -hex 32)
    export FORMLANDER_DATA_DIR=./storage
  3. Run the binary:
    Terminal window
    ./formlander
  1. Download the latest release from GitHub Releases
  2. Create a .env file:
    Terminal window
    FORMLANDER_ENV=production
    FORMLANDER_PORT=8080
    FORMLANDER_SESSION_SECRET=your-secret-here
    FORMLANDER_DATA_DIR=./storage
  3. Run the binary:
    Terminal window
    ./formlander

The binary will automatically detect and load the .env file from the current directory.

For production, use a reverse proxy like Cloudflare Tunnel, Nginx, or Caddy to add HTTPS and DDoS protection.

The simplest way to expose Formlander with automatic HTTPS:

Terminal window
# Install cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
chmod +x cloudflared && sudo mv cloudflared /usr/local/bin/
# Authenticate and create tunnel
cloudflared tunnel login
cloudflared tunnel create formlander
# Configure tunnel (~/.cloudflared/config.yml)
tunnel: <your-tunnel-id>
credentials-file: /root/.cloudflared/<tunnel-id>.json
ingress:
- hostname: forms.yourdomain.com
service: http://localhost:8080
- service: http_status:404
# Route DNS and start
cloudflared tunnel route dns formlander forms.yourdomain.com
cloudflared service install
sudo systemctl start cloudflared

No firewall configuration needed. Your Formlander instance is now at https://forms.yourdomain.com.

server {
listen 443 ssl http2;
server_name forms.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
forms.yourdomain.com {
reverse_proxy localhost:8080
}

Caddy automatically handles SSL certificates via Let’s Encrypt.

Webhook and email deliveries run in the same process. Keep the container running so queued jobs continue.

The storage/ directory contains everything Formlander needs to persist:

PathContents
storage/formlander.dbSQLite database (forms, submissions, settings)
storage/uploads/Uploaded files from form submissions

Docker volume is required. Without it, you lose all data when the container restarts:

Terminal window
# Always mount the storage volume
docker run -d \
-v $(pwd)/storage:/app/storage \
...

Storage sizing: Uploads are limited to 10MB per file. Plan your volume size based on expected submission volume.

Back up the storage/ directory to preserve your database, uploads, and logs. To migrate, copy storage/ to the new host and restart.