N8Forge Documentation

Admin guide

Use this guide when you install, configure, sell, provision, monitor, and maintain N8Forge as the platform operator.

Audience Founders, technical operators, support leads, and platform admins.
What it covers Install, billing, plans, provisioning placement, tenant operations, updates, and troubleshooting.
What it does not cover Partner presentation workflows and workspace how-to content.

Overview

Platform ownership

Admins own the full runtime and commercial configuration of the platform. That includes install decisions, billing credentials, plan design, tenant placement, infrastructure pools, runtime health, and incident response.

  • Core setup controls branding, billing credentials, landing-page content, AI provider keys, and docs visibility.
  • SaaSForge controls tenants, domains, provisioning jobs, provisioning servers, health checks, backups, runtime dependencies.
  • N8NForge controls managed instances, launch metadata, and workflow-template delivery.

Installation

First deploy
  • PHP 8.3+ with the Laravel and Wave requirements expected by the packaged app.
  • Application database on MySQL, MariaDB, PostgreSQL, or SQLite.
  • Queue and scheduler support because provisioning, templates, cleanup, and reminders depend on scheduled work.
  • Docker-capable runtime hosts for the local Linux-host driver or any SSH provisioning target.
1
Step 1

Extract the main package

Deploy the versioned install ZIP into the target app directory and point the web root at public/.

2
Step 2

Prepare writable paths

Ensure Laravel can write to storage/ and bootstrap/cache/, then provide a valid .env.

3
Step 3

Run the installer

Open /install, finish the environment and database steps, then create the first admin account.

4
Step 4

Log in and complete product setup

Move immediately into Setup, Plans, Themes, and provisioning resources before testing real customer flows.

First-day checklist

Recommended order
  • Configure Setup for General, Billing, Landing Page, AI, and Authentication.
  • Review plans and assign real billing price IDs plus any plan-level delivery mappings.
  • Choose the public theme and replace seeded marketing content.
  • Enable scheduler execution so provisioning and health automation can run.
  • Create provisioning resources such as SSH servers, external databases, and external storage backends if you will not rely only on the default local runtime path.
  • Run a real test subscription and confirm it creates a tenant, queues a job, and produces a usable runtime instance page.
  • or custom domains.

Setup page

Shared admin config

The Core Setup page is the main live configuration surface for branding, billing credentials, marketing content, AI provider keys, and authentication presentation.

General

Site title, description, logos, icons, analytics, and docs visibility in app menus.

Billing

Stripe or Paddle provider selection plus encrypted credential and webhook storage.

Landing Page

Hero, CTA, stats, pricing copy, testimonials, and public marketing sections.

AI

Encrypted provider keys for OpenAI, Anthropic, Grok, and DeepSeek.

Authentication

Shared auth-related setup exposed through the same admin flow.

Behavior

Database-backed setup values are loaded into runtime config and become the live source of truth.

Key env reference

Operator-level settings
Variable Default Purpose
SaaSForge — Base
SAASFORGE_WORKSPACE_SUFFIX Workspace Suffix appended to tenant workspace names
SAASFORGE_PROVISIONING_DRIVER docker Default runtime driver (docker / ssh)
SAASFORGE_PROVISIONING_QUEUE default Queue connection for provisioning jobs
SAASFORGE_PROVISIONING_BATCH_SIZE 10 Max jobs processed per scheduler run
SAASFORGE_SHOW_CADDY_FIX_BUTTONS false Show admin UI buttons for Caddy repair
SAASFORGE_BASE_DOMAIN app.url host Base domain for generated tenant subdomains
SAASFORGE_AUTO_SSL true Auto-provision SSL via Let's Encrypt
SAASFORGE_PRODUCT_TYPE n8nforge Default product type for new tenants
SAASFORGE_AUTO_CREATE_FIRST_INSTANCE true Auto-create the first n8n instance when a tenant is created from a subscription
SaaSForge — Docker Runtime
SAASFORGE_LINUX_RUNTIME_ENABLED true Enable the local Docker driver
SAASFORGE_RUNTIME_ROOT_PATH storage/.../runtime Host path for compose files and runtime data
SAASFORGE_DOCKER_BIN docker Docker binary path
SAASFORGE_DOCKER_COMPOSE_COMMAND docker compose Compose command
SAASFORGE_RUNTIME_NETWORK saasforge Docker network name for runtime containers
SAASFORGE_RUNTIME_IMAGE docker.n8n.io/n8nio/n8n:latest n8n container image tag
SAASFORGE_RUNTIME_BASE_PORT 23000 Starting port for container port mapping
SAASFORGE_RUNTIME_PORT_STEP 1 Port increment between instances
SAASFORGE_RUNTIME_WAIT_TIMEOUT 180 Seconds to wait for container health
SAASFORGE_RUNTIME_TIMEZONE UTC Timezone set on runtime containers
SAASFORGE_RUNTIME_CPUS 0.5 Default CPU limit per container
SAASFORGE_RUNTIME_MEMORY 600m Default memory limit per container
SAASFORGE_RUNTIME_MEMORY_SWAP 700m Default swap limit per container
SAASFORGE_RUNTIME_RUNNERS_ENABLED true Enable n8n task runners
SaaSForge — Caddy (Docker)
SAASFORGE_RUNTIME_CADDY_ENABLED true Manage Caddy reverse-proxy sites
SAASFORGE_RUNTIME_CADDY_BIN caddy Caddy binary path
SAASFORGE_RUNTIME_CADDY_RELOAD true Run caddy reload after site changes
SAASFORGE_RUNTIME_CADDY_MAIN_CONFIG /etc/caddy/Caddyfile Main Caddyfile path
SAASFORGE_RUNTIME_CADDY_SITE_DIR storage/.../caddy-sites Directory for per-instance site files
SAASFORGE_RUNTIME_CADDY_TLS_EMAIL MAIL_FROM_ADDRESS Email for Let's Encrypt certificate notices
SaaSForge — SSO / OIDC
SAASFORGE_RUNTIME_N8N_SSO_ENABLED false Enable OIDC SSO for instance login
SAASFORGE_RUNTIME_N8N_SSO_PROTOCOL oidc SSO protocol (oidc)
SAASFORGE_RUNTIME_N8N_SSO_MANAGED_BY_ENV true Inject SSO config via container env vars
SAASFORGE_RUNTIME_N8N_SSO_USER_ROLE_PROVISIONING disabled Auto-provision n8n user roles on login
SAASFORGE_RUNTIME_N8N_SSO_OIDC_LOGIN_ENABLED true Show OIDC login button on n8n sign-in
SAASFORGE_RUNTIME_N8N_SSO_OIDC_CLIENT_ID n8n-sso OIDC client ID
SAASFORGE_RUNTIME_N8N_SSO_OIDC_CLIENT_SECRET generated OIDC client secret (regenerated on install)
SAASFORGE_RUNTIME_N8N_SSO_OIDC_DISCOVERY_ENDPOINT app.url /.well-known/… OIDC discovery URL
SAASFORGE_RUNTIME_N8N_SSO_OIDC_PROMPT empty OIDC prompt parameter (login, consent, etc.)
SAASFORGE_RUNTIME_N8N_SSO_OIDC_ACR_VALUES empty OIDC acr_values parameter
SaaSForge — SSH Runtime
SAASFORGE_SSH_RUNTIME_ENABLED true Enable the SSH runtime driver
SAASFORGE_SSH_CONNECT_TIMEOUT 10 SSH connection timeout in seconds
SAASFORGE_SSH_WAIT_TIMEOUT 180 Wait timeout for remote operations
SAASFORGE_SSH_RUNTIME_ROOT_PATH /var/lib/saasforge/runtime Remote path for runtime files
SAASFORGE_SSH_DOCKER_BIN docker Remote Docker binary path
SAASFORGE_SSH_DOCKER_COMPOSE_COMMAND docker compose Remote compose command
SAASFORGE_SSH_RUNTIME_IMAGE docker.n8n.io/n8nio/n8n:latest Remote n8n image tag
SAASFORGE_SSH_RUNTIME_BASE_PORT 23000 Remote base port
SAASFORGE_SSH_RUNTIME_CPUS 0.5 Remote CPU limit
SAASFORGE_SSH_RUNTIME_MEMORY 600m Remote memory limit
SAASFORGE_SSH_RUNTIME_MEMORY_SWAP 700m Remote swap limit
SAASFORGE_SSH_RUNTIME_RUNNERS_ENABLED true Remote task runners
SAASFORGE_SSH_CADDY_RELOAD true Remote Caddy reload after site changes
SAASFORGE_SSH_CADDY_BIN caddy Remote Caddy binary path
SAASFORGE_SSH_CADDY_MAIN_CONFIG /etc/caddy/Caddyfile Remote main Caddyfile
SAASFORGE_SSH_CADDY_SITE_DIR /etc/caddy/sites-enabled/saasforge Remote Caddy site files directory
SaaSForge — Backups & Health
SAASFORGE_BACKUPS_ENABLED true Enable scheduled runtime backups
SAASFORGE_BACKUPS_MAX_PER_TENANT 7 Max backups retained per tenant
SAASFORGE_HEALTH_CHECKS_ENABLED true Enable scheduled health checks
SAASFORGE_HEALTH_CURL_TIMEOUT 5 Health check HTTP timeout in seconds
SAASFORGE_HEALTH_FAILURE_THRESHOLD 3 Consecutive failures before instance marked unhealthy
SaaSForge — Domains & TLS
SAASFORGE_CADDY_ON_DEMAND_TLS_ENABLED true Enable Caddy on-demand TLS for custom domains
N8NForge — Instances
N8NFORGE_PRODUCT_TYPE n8nforge Product type for N8NForge instances
N8NFORGE_DEFAULT_N8N_VERSION latest Default n8n version tag for new instances
N8NFORGE_INSTANCE_SUBFOLDER / Subfolder path for instance URL
N8NFORGE_INSTANCE_RANDOM_SLUG_PREFIX inst Prefix for random slug when instance slug would repeat the tenant slug
N8NForge — Templates
N8NFORGE_AUTO_INSTALL_FEATURED true Auto-queue featured templates on new workspaces
N8NFORGE_AUTO_INSTALL_STATUS queued Status for auto-installed templates
N8NFORGE_MANUAL_INSTALL_STATUS queued Status for manually installed templates
N8NForge — Metrics
N8NFORGE_METRICS_POLLING false Enable background metrics polling via scheduler
N8NFORGE_METRICS_POLLING_INTERVAL 15 Minutes between metric collection cycles
N8NFORGE_METRICS_RETENTION_DAYS 60 Days to retain metric snapshots before cleanup
N8NForge — Updates
N8NFORGE_UPDATE_SERVER_URL empty Update server URL for platform releases
N8NFORGE_UPDATE_REQUEST_TIMEOUT 120 Timeout for update server requests
Admin versus env

Branding, billing keys, landing copy, and docs visibility are meant to be changed from admin. Runtime topology, Docker and proxy paths, domain defaults, and SSO settings remain infrastructure configuration.

Instance resource limits

Every n8n container gets default CPU, memory, and swap limits. These can be overridden per instance from the admin panel.

  • Open Automation → Managed Instances → Edit on the instance you want to adjust.
  • The Resource Overrides section lets you set CPU, memory, memory swap, and toggle task runners.
  • When saved, the instance restarts automatically to apply the new limits.

Metrics collection

Each n8n instance exposes a metrics endpoint that feeds the customer dashboard stat cards, history bars, and the admin Top Resource Consumers widget (shows the 10 instances with highest memory usage).

Metrics are captured automatically when customers view their dashboard. An optional background poller can be enabled via N8NFORGE_METRICS_POLLING=true to collect data across all instances regardless of dashboard activity. Snapshots are stored in the n8nforge_instance_metrics table.

Retention & cleanup

Old snapshots can be pruned automatically to keep the metrics table lean:

  • Retention window: controlled by N8NFORGE_METRICS_RETENTION_DAYS (default 60). Rows older than this threshold are candidates for deletion.
  • Manual cleanup: php artisan n8nforge:clean-metrics — add --dry-run to preview without deleting.
  • Scheduled cleanup: the framework console kernel registers n8nforge:clean-metrics on the daily schedule. Make sure the Laravel scheduler runs every minute via cron: * * * * * cd /path/to/project && php artisan schedule:run.

Plans and billing

Commercial delivery
  • Provider choose Stripe or Paddle in Setup.
  • Credentials save publishable, secret, and webhook values in encrypted storage.
  • Plan pricing enter monthly, yearly, or one-time provider price IDs on the plan resource.
  • Role assignment map each plan to the correct post-subscription role.
  • Free tier handling mark the fallback plan if unsubscribed users should keep some access.
  • Delivery policy use the plan resource to map provisioning servers, external databases, and external storage pools to each offer.
Plan reference behavior

SaaSForge stores the active Wave plan_id on the tenant as product_reference. That value is what server and runtime dependency selectors use when applying plan-level placement rules.

Provisioning model

Runtime orchestration

Provisioning is driver-based and job-driven. Initial deploy, suspend, resume, restart, redeploy, and domain sync are all tracked lifecycle jobs.

  • Driver selection persists as provisioning_driver on the tenant.
  • Server placement persists as provisioning_server_id so later health, backup, and lifecycle actions use the same host.
  • Dependency placement persists selected external database and storage backends so restarts and redeploys keep using the same infrastructure choices.
  • Provisioning jobs are the audit trail for all tracked runtime actions.
Provisioning resources
Local Linux-host driver

Uses the application host as the runtime host.

SSH server driver

Uses reusable remote provisioning servers selected from plan mappings.

Future providers

The same placement model can support later API-based runtime providers.

Provisioning servers

Provisioning servers define SSH connection settings, runtime defaults, reverse proxy behavior, and optional plan-level tenant capacity. Treat them as the actual hosts that carry tenant traffic.

How domain wiring actually works

Domain sync does not register domains with a DNS provider and does not use a wildcard Caddy listener with an ask endpoint back to the main app. Instead, SaaSForge writes a concrete Caddy site file for each tenant using that tenant's exact domain_hosts list, then reloads Caddy and updates the n8n container environment so N8N_HOST, N8N_EDITOR_BASE_URL, and WEBHOOK_URL point at the tenant's primary domain.

Provisioning server requirements
  • Docker and Compose must already be installed on the provisioning host and available to the configured deploy user.
  • Caddy must already be installed if you enable reverse-proxy management for that server. SaaSForge writes per-tenant site files and reloads Caddy, but it does not install or bootstrap Caddy for you.
  • A writable runtime root must exist for compose files, env files, logs, backups, and tenant data.
  • A shared Docker network must be available or creatable by the deploy user for tenant containers.
  • DNS must point tenant domains at the provisioning host or fronting load balancer before HTTPS traffic can succeed.
  • Firewall and ports must allow public HTTP/HTTPS traffic to the reverse proxy and local container traffic on the allocated host ports.
Admin setup workflow
  1. Prepare the host with Docker, Docker Compose, Caddy, and a deploy user that can write the runtime directories and reload Caddy.
  2. Point DNS for any tenant or base-domain records at that host or its fronting proxy/load balancer.
  3. Create a provisioning server in admin with the SSH connection, root path, Docker command names, network, and optional Caddy paths.
  4. Assign the server to plans so new tenants can be placed onto that host automatically.
  5. Run a real provisioning test and confirm the tenant compose files, Caddy site file, Caddy reload, HTTPS response, and n8n launch URL all succeed.
What SaaSForge does automatically
  • Creates tenant runtime files such as the compose file, env file, log path, backup path, and tenant data path under the configured runtime root.
  • Creates or updates a tenant-specific Caddy site file that contains the tenant's exact domain list and reverse proxies traffic to that tenant's allocated host port.
  • Starts, stops, restarts, or redeploys the tenant container with the configured Docker and Compose commands.
  • Reloads Caddy after writing or removing a tenant site file when reverse proxy management is enabled.
  • Updates n8n runtime URLs so the primary tenant domain becomes the editor base URL and webhook base URL.
What SaaSForge does not do for you
  • It does not install Docker or Docker Compose on the provisioning host.
  • It does not install or bootstrap Caddy on the provisioning host.
  • It does not create DNS records with Cloudflare, Route53, or any other DNS provider.
  • It does not create a wildcard or catch-all Caddy listener that asks the central app whether a domain is allowed.
  • It does not manage operating-system firewall rules or cloud load balancer listeners for you.
Recommended host preparation

Treat provisioning hosts as pre-built runtime targets. SaaSForge expects the server to be ready for deployments before you save it in admin.

#!/usr/bin/env bash
set -euo pipefail

DEPLOY_USER="${1:-deploy}"
HOSTNAME="$(hostname -f)"

_has_cmd() { command -v "$1" || return 1; }
_deb_installed() { dpkg -s "$1" || return 1; }
_install_if_missing() {
    local missing=()
    for pkg in "$@"; do
        _deb_installed "$pkg" || missing+=("$pkg")
    done
    [[ ${#missing[@]} -eq 0 ]] || sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq "${missing[@]}"
}

echo "=== 1. System updates ==="
sudo apt-get update -qq
sudo apt-get upgrade -y -qq
_install_if_missing curl ufw unattended-upgrades

if ! swapon --show | grep -q .; then
    sudo fallocate -l 1G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
fi

echo "=== 2. Docker ==="
if ! _has_cmd docker; then
    for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
        sudo apt-get remove -y "$pkg" || true
    done
    curl -fsSL https://get.docker.com | sudo bash
fi
_install_if_missing docker-compose-plugin

echo "=== 3. Docker daemon config ==="
sudo mkdir -p /etc/docker
printf '%s\n' '{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"},"live-restore":true,"storage-driver":"overlay2"}' \
    | sudo tee /etc/docker/daemon.json
if _has_cmd dockerd; then
    sudo systemctl restart docker
fi

echo "=== 4. Caddy ==="
if ! _has_cmd caddy; then
    _install_if_missing debian-keyring debian-archive-keyring apt-transport-https
    sudo mkdir -p /usr/share/keyrings
    if [[ ! -f /usr/share/keyrings/caddy-stable-archive-keyring.gpg ]]; then
        curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
            | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    fi
    if [[ ! -f /etc/apt/sources.list.d/caddy-stable.list ]]; then
        curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
            | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    fi
    sudo apt-get update -qq
    _install_if_missing caddy
fi

echo "=== 5. Deploy user & runtime dirs ==="
sudo id -u "$DEPLOY_USER" || sudo useradd -m -s /bin/bash "$DEPLOY_USER"
sudo usermod -aG docker "$DEPLOY_USER"
sudo mkdir -p /var/lib/saasforge/runtime
sudo chown -R "$DEPLOY_USER":"$DEPLOY_USER" /var/lib/saasforge/runtime
sudo mkdir -p /etc/caddy/sites-enabled/saasforge

echo "=== 6. Kernel tuning ==="
printf 'fs.file-max = 100000\nvm.max_map_count = 262144\nnet.core.somaxconn = 1024\n' \
    | sudo tee /etc/sysctl.d/99-saasforge.conf
sudo sysctl --system

echo "=== 7. Firewall ==="
if sudo ufw status | grep -q 'Status: active'; then
    for port in ssh 80/tcp 443/tcp; do
        sudo ufw status | grep -q "$port" || sudo ufw allow "$port"
    done
else
    _install_if_missing ufw
    sudo ufw --force reset
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    sudo ufw allow ssh
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw --force enable
fi

echo "=== 8. Enable services ==="
sudo systemctl enable --now docker

# Write a minimal Caddyfile so caddy can start
if ! caddy validate --config /etc/caddy/Caddyfile; then
    printf ':80 {\n    respond "SaaSForge provisioning host"\n}\n\nimport /etc/caddy/sites-enabled/saasforge/*\n' \
        | sudo tee /etc/caddy/Caddyfile
fi
cd /etc/caddy && caddy start
echo "Caddy started in /etc/caddy/"

# unattended-upgrades is a timer, not a service
sudo systemctl enable unattended-upgrades || true
sudo systemctl start unattended-upgrades || true

echo "=== 9. Verification ==="
echo -n "Docker: "; sudo -u "$DEPLOY_USER" docker version --format '{{.Server.Version}}'
echo -n "Compose: "; sudo -u "$DEPLOY_USER" docker compose version --short
echo -n "Caddy: "; caddy version
echo -n "UFW: "; sudo ufw status | head -1

echo ""
echo "Host $HOSTNAME ready. Add it as a Provisioning Server in admin.
  Host     : $HOSTNAME
  Port     : 22
  Username : $DEPLOY_USER"
Caddy main config expectation

The main Caddy config should import the SaaSForge-managed site directory. SaaSForge writes individual tenant site files into that directory and then reloads Caddy. If you want on-demand TLS protection for tenant and custom domains, add the global on_demand_tls ask endpoint that points at the central app.

# Example /etc/caddy/Caddyfile excerpt
{
    email admin@example.com

    on_demand_tls {
        ask https://app.example.com/saasforge/caddy/on-demand-tls
    }
}

import /etc/caddy/sites-enabled/saasforge/*

When SAASFORGE_CADDY_ON_DEMAND_TLS_ASK_URL is configured, SaaSForge-generated site files switch to tls { on_demand } and expect the main Caddy config to expose the matching ask URL above.

DNS expectation

Point tenant domains or delegated subdomains at the provisioning host or its fronting load balancer before expecting HTTPS to succeed. Domain sync only updates the runtime and Caddy side after the hostname is already routed to the host.

First connection trust prompt

A brand-new SSH target can fail on its first deployment if the app host has never trusted that server before. When strict host key checking is enabled, trust the host in known_hosts first or disable strict checking temporarily for the first test.

External runtime dependencies

Database and storage pools
External databases

Managed PostgreSQL pools with host, port, database, credentials, schema, pool sizing, optional SSL material, and plan-level capacity mapping.

External storage

Managed S3-compatible binary-data storage backends with endpoint, protocol, bucket, region, credentials, and plan-level capacity mapping.

  • Fallback behavior remains local SQLite plus local filesystem storage when no external resource is assigned.
  • Tenant overrides can explicitly pin a tenant to a specific database or storage backend.
  • Plan mappings let you keep infrastructure placement policy on the product offer instead of per-tenant manual edits.
n8n storage licensing

External binary-data storage depends on n8n enterprise licensing. If you are not intentionally using that feature, leave storage unmapped and back up the tenant data directory on the runtime host.

Tenant operations

Day-two admin work
  • Tenant edit page is for ownership, plan changes, infrastructure overrides, and primary record maintenance.
  • Tenant instance page is for day-two operations such as health review, uptime visibility, backup creation, restart, and redeploy.
  • Provisioning feedback allows readiness callbacks to close a running lifecycle job after the runtime reports back.
  • Runtime metadata stores base URL, launch URL, host port, latest failure details, and dependency selections.
Use the instance page first

When a tenant looks unhealthy, open the instance page before taking action. Review the latest health snapshot, uptime, active host, latest backup, and last provisioning job so you can choose the right response.

Scheduler and commands

Required automation

This is one of the most important parts of setup. If the scheduler is not running, new tenants stay queued, template installs wait, health checks stop, backups stop, and scheduled account actions do not run.

Simple rule

You do not create one cron job for each command below.

You create one server cron job that runs php artisan schedule:run every minute. Laravel then runs the correct commands automatically.

1
Step 1

Find the app folder

Open the folder where N8Forge is installed. This is the folder that contains the artisan file.

2
Step 2

Test the scheduler once

Run php artisan schedule:run from that folder. If it works, you can set the server to run the same command automatically every minute.

3
Step 3

Add one cron job on the server

In your server panel or cron manager, create a job that runs every minute. Replace the sample path below with your real N8Forge install path and PHP path.

* * * * * cd /path/to/n8forge && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

If your host asks for separate fields, use:

  • Frequency: every minute
  • Working folder: the N8Forge folder that contains artisan
  • Command: /usr/bin/php artisan schedule:run
4
Step 4

Confirm it is working

After a few minutes, create or update something that uses automation and confirm the related action moves forward. A newly created tenant should not remain stuck in queued for long if the scheduler is active.

If you use more than one app server

Run the cron job on only one main app server unless you have intentionally designed a clustered scheduler setup.

Command Schedule Purpose
subscriptions:cancel-expired Every hour Cancels expired subscriptions automatically
saasforge:send-suspension-reminders Every hour Sends scheduled suspension reminders
saasforge:process-provisioning Every minute Processes tenant create, restart, redeploy, suspend, and destroy jobs
saasforge:check-runtime-health Every five minutes Updates runtime health snapshots and instance status data
saasforge:run-backups Daily Creates tenant backups
n8nforge:process-template-installs Every minute Processes queued template installs for managed workspaces
accounts:process-deletions Daily Deletes accounts that reached the end of their deletion grace period
activity:clean Daily Removes old activity logs based on retention settings
Quick check after setup

Create a test tenant. If the scheduler is working, provisioning should begin shortly instead of sitting in queued.

If jobs stay queued

The cron job is missing, using the wrong path, using the wrong PHP binary, or running in the wrong folder.

If you are not technical

Send your hosting provider or server admin the cron command above and ask them to run it every minute on the N8Forge application server.

Backups and restore

Automated backups capture the full n8n data directory, including the SQLite database, credentials, and workflow files.

  • Scope: The entire /home/node/.n8n directory is tar'd, so the SQLite database is always included.
  • Schedule: saasforge:run-backups runs daily. Retention is configurable via SAASFORGE_BACKUPS_MAX_PER_TENANT (default 7).
  • Manual backup: From the instance edit page at Automation → Managed Instances → Edit → Backup.
  • Restore: From the instance view page (Automation → Managed Instances → {instance} → View), scroll to the Backups section and click Restore on a succeeded backup. The container stops, the data directory is replaced, and the container restarts.
  • Restore status is shown as a badge on the backup card. All restore operations are logged to the activity log.
  • SSH driver: Backup files are downloaded locally, then uploaded back to the remote server during restore. Both Docker and SSH drivers are supported.

Activity log

A unified activity log at SaaS → Activity Log shows all platform operations in reverse chronological order.

Action type Source What it tracks
saasforge_job_* Provisioning Every job start, success, and failure
n8nforge_template_* Templates Template installs and failures
saasforge_runtime_backup_* Backups Backup queued, completed, or failed
saasforge_runtime_restore_* Restore Restore started, completed, or failed
saasforge_runtime_health_* Health Health check results
saasforge_runtime_*_queued Actions Restart, redeploy, or destroy queued

Filter by action type or time period (today, yesterday, last 7/30 days). Error details are shown inline. Logs older than the configured retention period are cleaned automatically.

Production requirement

Without the every-minute scheduler cron job, provisioning, template delivery, reminders, cleanup, backups, health monitoring, and scheduled account actions will drift or stop.

Updates and deployment tooling

Release operations
  • Admin → Updates verifies the purchase code, checks for the latest release, and applies downloads when configured.
  • php artisan n8forge:update runs pending update tasks for the current install.
  • php artisan n8forge:update --download downloads and applies the latest release before migrations and cache refresh.
  • ops/scripts/build-mainfiles.sh builds install and update packages.
  • ops/scripts/push-demo.sh helps deploy the N8Forge app itself, not tenant runtimes.
Separation of concerns

The ops/ scripts are for deploying the N8Forge application. They are not a replacement for SaaSForge provisioning servers or tenant runtime placement.

Maintenance workflow

Recommended routine
  • Daily review provisioning jobs, health checks, failed backups, and account notifications. Open the instance page for any degraded workspace.
  • After plan changes verify billing IDs, role mapping, and provisioning, database, and storage assignments.
  • After server changes confirm SSH credentials, Docker access, proxy paths, and capacity limits.
  • After dependency changes validate one real tenant deployment before treating the change as complete.
  • Before updates take backups and verify restore confidence for both the app and tenant runtime data.
Activity logging

Keep ACTIVITY_LOG_ENABLED active if you need an audit trail for runtime actions such as health checks, backups, restart, or redeploy operations.

Troubleshooting

Common admin issues
A subscription does not create a tenant

Check the active plan, subscription status, role mapping, and whether the observer, queue, and scheduler path is functioning.

A tenant is queued but not provisioning

Confirm saasforge:process-provisioning is scheduled and that the selected driver, server, and optional runtime dependencies are valid.

SSH provisioning fails immediately

Verify host, port, username, key or password, host-key policy, Docker access, remote paths, and whether the deploy user can write files and reload the reverse proxy.

A domain saves but still does not open

Check that DNS points at the correct host, the tenant Caddy site file exists on that provisioning server, Caddy reloaded successfully, and the primary domain matches the n8n runtime base URL. There is no central wildcard ask-endpoint flow in the current implementation.

A runtime fails after enabling external database or storage

Check credentials, SSL settings, S3 region formatting, enterprise licensing, and whether the plan or tenant still points at the intended dependency pool.

An instance looks unhealthy or stale

Open the tenant instance page first, review the last health result and active host, then decide between health check, backup, restart, or redeploy.