Skip to content

Instantly share code, notes, and snippets.

@niradler
Last active August 9, 2026 11:29
Show Gist options
  • Select an option

  • Save niradler/580fd522295f47d2d1780d74fd2ef83c to your computer and use it in GitHub Desktop.

Select an option

Save niradler/580fd522295f47d2d1780d74fd2ef83c to your computer and use it in GitHub Desktop.
ScadFlow public Docker install — pull niradler/scadflow, no private repo needed
#!/bin/sh
set -eu
echo "ScadFlow: preparing the database login used by the app..."
if [ -z "${SCADFLOW_DB_PASSWORD:-}" ]; then
echo "ScadFlow: missing SCADFLOW_DB_PASSWORD." >&2
echo "ScadFlow: run setup-docker.sh (or setup-docker.ps1) first, then start again." >&2
exit 1
fi
psql --set ON_ERROR_STOP=1 \
--username "$POSTGRES_USER" \
--dbname "$POSTGRES_DB" \
--set app_password="$SCADFLOW_DB_PASSWORD" <<'SQL'
SELECT format('CREATE ROLE scadflow_app LOGIN PASSWORD %L', :'app_password')
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'scadflow_app')
\gexec
GRANT CONNECT ON DATABASE scadflow TO scadflow_app;
GRANT USAGE, CREATE ON SCHEMA public TO scadflow_app;
SQL
echo "ScadFlow: database login ready."

ScadFlow

Design printable 3D models in your browser — start from templates, preview instantly, leave notes on the model, and keep full control of every change.

ScadFlow helps you create and refine 3D-printable models without fighting complex tools.

Open it in your browser and:

  • Start from ready-made starters (keycaps, enclosures, trays, and more)
  • See a live 3D preview as you work
  • Pin notes right on the model so feedback stays with the design
  • Ask an AI assistant for ideas — nothing changes until you approve it
  • Save versions and download files ready for your printer

Built for beginners who want clear steps, and for makers who want a careful review loop before anything is final.

Runs on your own computer. Your designs stay with you.

Image: niradler/scadflow:0.0.1
Open in browser: http://127.0.0.1:3000

Keep it on your own computer only for now. ScadFlow does not yet have sign-in, so do not share it on a home network or the public internet.

What you need

  • Docker Desktop (Windows or Mac) or Docker Engine with Compose on Linux
  • About 4 GB of memory available to Docker
  • Docker Desktop must be running before you start

Install

  1. Download the public install bundle (Compose file + setup scripts):
    https://gist.github.com/niradler/580fd522295f47d2d1780d74fd2ef83c
    Use Download ZIP, or clone the gist, then open that folder in a terminal.
  2. Create your private passwords and data folders:
# macOS / Linux
sh setup-docker.sh

# Windows PowerShell
.\setup-docker.ps1
  1. Start ScadFlow:
docker compose up --detach
  1. Open http://127.0.0.1:3000

The first start downloads the image and can take a few minutes. Check that it is ready with:

docker compose ps

When scadflow shows as healthy, you are ready.

Everyday use

From the same install folder:

docker compose ps
docker compose logs --follow scadflow
docker compose restart scadflow
docker compose down

docker compose down stops ScadFlow but keeps your saved designs on disk.

Update without losing designs

Your designs live under ~/.scadflow, not inside the install folder. To update:

  1. Download a fresh copy of the install bundle.
  2. Copy your existing .env.docker and .env.docker.postgres into the new folder (do not re-run setup unless you intend to start over).
  3. Start again:
docker compose pull
docker compose up --detach

Optional: use another local port for one run:

SCADFLOW_PORT=8080 docker compose up --detach

Where your files live

Folder What it stores
~/.scadflow/postgres/ Database
~/.scadflow/data/ App data
~/.scadflow/workspace/ Your project folders

On Windows that is usually %USERPROFILE%\.scadflow\.

Passwords stay next to compose.yaml in .env.docker and .env.docker.postgres. Do not share or commit those files.

If you later move off Docker to a local install, you can point that install at the same workspace (and review data) folders manually — your project files are already there.

Install bundle files

The public gist includes:

File Purpose
compose.yaml Starts ScadFlow from this Docker Hub image (no source code needed)
setup-docker.sh / setup-docker.ps1 One-time password and folder setup
001-scadflow-app.sh First-launch database setup
name: scadflow
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
env_file:
- .env.docker.postgres
environment:
POSTGRES_DB: scadflow
POSTGRES_INITDB_ARGS: --data-checksums
POSTGRES_USER: scadflow_owner
volumes:
- type: bind
source: ${HOME}/.scadflow/postgres
target: /var/lib/postgresql/data
- type: bind
source: ./001-scadflow-app.sh
target: /docker-entrypoint-initdb.d/001-scadflow-app.sh
read_only: true
healthcheck:
test: ["CMD-SHELL", "pg_isready -U scadflow_owner -d scadflow"]
interval: 5s
timeout: 3s
retries: 20
start_period: 10s
security_opt:
- no-new-privileges:true
networks:
- backend
scadflow:
image: niradler/scadflow:0.0.1
pull_policy: always
restart: unless-stopped
init: true
env_file:
- .env.docker
environment:
API_PORT: "3001"
DEV_WORKSPACE_ID: demo-workspace
OPENSCAD_BINARY: /usr/bin/openscad
PERSISTENCE_DRIVER: postgres
SCADFLOW_DATA_DIR: /data
SCADFLOW_WORKSPACE_DIR: /workspace
SCADFLOW_TOOLS_DIR: /data/tools
WEB_PORT: "3000"
depends_on:
postgres:
condition: service_healthy
restart: true
ports:
- "127.0.0.1:${SCADFLOW_PORT:-3000}:3000"
volumes:
- type: bind
source: ${HOME}/.scadflow/data
target: /data
- type: bind
source: ${HOME}/.scadflow/workspace
target: /workspace
read_only: true
tmpfs:
- /tmp:size=512m,mode=1777
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
healthcheck:
test:
[
"CMD",
"node",
"-e",
"fetch('http://127.0.0.1:3000/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))",
]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
stop_grace_period: 30s
networks:
- backend
- frontend
networks:
backend:
internal: true
frontend:
$ErrorActionPreference = "Stop"
$projectRoot = $PSScriptRoot
$applicationEnvironmentPath = Join-Path $projectRoot ".env.docker"
$postgresEnvironmentPath = Join-Path $projectRoot ".env.docker.postgres"
$homeDirectory = $env:HOME
if ([string]::IsNullOrWhiteSpace($homeDirectory)) {
$homeDirectory = $env:USERPROFILE
}
if ([string]::IsNullOrWhiteSpace($homeDirectory)) {
throw "HOME / USERPROFILE is not set. Open a normal user PowerShell window and try again."
}
$dataRoot = Join-Path $homeDirectory ".scadflow"
$existingEnvironmentFiles = @($applicationEnvironmentPath, $postgresEnvironmentPath) |
Where-Object { Test-Path -LiteralPath $_ }
if ($existingEnvironmentFiles.Count -gt 0) {
Write-Host "Passwords: $applicationEnvironmentPath and $postgresEnvironmentPath"
Write-Host "Design data: $dataRoot"
throw "Docker environment already exists; no file was modified: $($existingEnvironmentFiles -join ', ')"
}
function New-RandomPassword {
$bytes = [byte[]]::new(32)
[System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes)
return [Convert]::ToBase64String($bytes).TrimEnd("=").Replace("+", "-").Replace("/", "_")
}
@(
(Join-Path $dataRoot "postgres"),
(Join-Path $dataRoot "data"),
(Join-Path $dataRoot "workspace")
) | ForEach-Object { [System.IO.Directory]::CreateDirectory($_) | Out-Null }
$ownerPassword = New-RandomPassword
$applicationPassword = New-RandomPassword
$utf8WithoutBom = [System.Text.UTF8Encoding]::new($false)
[System.IO.File]::WriteAllText(
$applicationEnvironmentPath,
"DATABASE_URL=postgresql://scadflow_app:${applicationPassword}@postgres:5432/scadflow`n",
$utf8WithoutBom
)
[System.IO.File]::WriteAllText(
$postgresEnvironmentPath,
"POSTGRES_DB=scadflow`nPOSTGRES_USER=scadflow_owner`nPOSTGRES_PASSWORD=${ownerPassword}`nSCADFLOW_DB_PASSWORD=${applicationPassword}`n",
$utf8WithoutBom
)
Write-Host "Created isolated Docker credentials next to this compose file."
Write-Host "Created design folders under $dataRoot"
Write-Host "Those folders stay when you replace this gist folder for an update."
Write-Host "Next: docker compose up --detach"
#!/bin/sh
set -eu
project_root=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
application_environment_path="$project_root/.env.docker"
postgres_environment_path="$project_root/.env.docker.postgres"
data_root="${HOME}/.scadflow"
if [ -z "${HOME:-}" ]; then
echo "HOME is not set. Open a normal user terminal and try again." >&2
exit 1
fi
if [ -e "$application_environment_path" ] || [ -e "$postgres_environment_path" ]; then
echo "Docker environment already exists; no file was modified." >&2
echo "Passwords: $application_environment_path and $postgres_environment_path" >&2
echo "Design data: $data_root" >&2
exit 1
fi
random_password() {
od -An -N32 -tx1 /dev/urandom | tr -d ' \n'
}
umask 077
mkdir -p \
"$data_root/postgres" \
"$data_root/data" \
"$data_root/workspace"
owner_password=$(random_password)
application_password=$(random_password)
printf 'DATABASE_URL=postgresql://scadflow_app:%s@postgres:5432/scadflow\n' \
"$application_password" > "$application_environment_path"
printf 'POSTGRES_DB=scadflow\nPOSTGRES_USER=scadflow_owner\nPOSTGRES_PASSWORD=%s\nSCADFLOW_DB_PASSWORD=%s\n' \
"$owner_password" "$application_password" > "$postgres_environment_path"
echo "Created isolated Docker credentials next to this compose file."
echo "Created design folders under $data_root"
echo "Those folders stay when you replace this gist folder for an update."
echo "Next: docker compose up --detach"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment