This application allows you to create demo shops in a docker environment.
cp .env.example .env # edit docker socket path and db credentials
cp api/config.example.yml api/config.yml # edit with your API settingsOr using bab:
bab setupbab devThis starts the database via Docker, then runs the API and web frontend dev servers in parallel.
- Web Frontend: http://localhost:5173
- API: http://localhost:8080
- SSH Proxy: port 2222 (when
ssh.enabled: true)
| Component | Directory | Stack |
|---|---|---|
| Api | /api/ |
Go, Echo, GORM, PostgreSQL, JWT Auth |
| Web | /web/ |
Vue 3, Shadcn-vue, TypeScript, pnpm |
Copy api/config.example.yml to api/config.yml and edit with your settings.
The example is pre-configured for local development (localhost database, dev JWT secret, Traefik disabled).
logging:
level: "debug"
format: "text"
server:
port: 8080
app_url: "http://localhost:8080"
allowed_origins:
- "http://localhost:5173"
- "http://localhost:8000"
database:
host: "localhost"
port: 5432
user: "shopshredder"
password: "sandXbox_mrpix2025"
name: "shopshredder"
sslmode: "disable"
auth:
jwt_secret: "local-dev-secret"
jwt_ttl_minutes: 480
guest_jwt_ttl_minutes: 43200
guest_cookie_name: "shopshredder_guest"
sandbox:
url_prefix: "sandbox-"
url_suffix: ".localhost"
default_lifetime: 60
max_lifetime: 1440
cleanup_interval_seconds: 60
internal_port: 80
docker:
mode: "port"
network: "internal"
traefik_enable: false
traefik_entrypoints: "websecure"
traefik_certresolver: "production"
traefik_middlewares: "sandbox-middleware@file,https-redirect@file"
snapshot_author: "shopshredder-api"
snapshot_comment: "Sandbox snapshot created by Shopshredder API"
storage:
thumbnail_dir: "storage/thumbnails"
guard:
max_total_sandboxes: 32
max_sandboxes_per_ip: 5
max_sandboxes_per_user: 10
terminal:
max_sessions_per_sandbox: 2
idle_timeout_minutes: 15
max_duration_minutes: 120
ssh:
enabled: true
port: 2222
host: ""| Section | Key | Type | Default | Description |
|---|---|---|---|---|
| logging | level | string | "info" | Log level: debug, info, warn, error. |
| format | string | "json" | Log format: json (production) or text (colorized dev). | |
| server | port | int | 8080 | The port on which the server runs. |
| app_url | string | "http://localhost:8080" | The base URL of the application. | |
| allowed_origins | array | [] | List of allowed CORS origins. | |
| database | host | string | "localhost" | Database host address. |
| port | int | 5432 | Database port. | |
| user | string | "shopshredder" | Database username. | |
| password | string | "sandXbox_mrpix2025" | Database password. | |
| name | string | "shopshredder" | Database name. | |
| sslmode | string | "disable" | PostgreSQL SSL mode. | |
| auth | jwt_secret | string | "local-dev-secret" | JWT signing secret. |
| jwt_ttl_minutes | int | 480 | JWT token TTL in minutes. | |
| guest_jwt_ttl_minutes | int | 43200 | Guest JWT token TTL in minutes. | |
| guest_cookie_name | string | "shopshredder_guest" | Cookie name for guest tokens. | |
| sandbox | url_prefix | string | "sandbox-" | Prefix for sandbox URLs. |
| url_suffix | string | ".localhost" | Suffix for sandbox URLs. | |
| default_lifetime | int | 60 | Default sandbox lifetime in minutes. | |
| max_lifetime | int | 1440 | Maximum sandbox lifetime in minutes. | |
| cleanup_interval_seconds | int | 60 | Interval between cleanup runs in seconds. | |
| internal_port | int | 80 | Internal container port. | |
| docker | mode | string | "port" | Docker mode ("port" or "traefik"). |
| network | string | "internal" | Docker network name. | |
| traefik_enable | bool | false | Enable Traefik integration. | |
| traefik_entrypoints | string | "websecure" | Traefik entrypoints. | |
| traefik_certresolver | string | "production" | Traefik certificate resolver. | |
| traefik_middlewares | string | "" | Traefik middlewares (comma-separated). | |
| snapshot_author | string | "shopshredder-api" | Author for container snapshots. | |
| snapshot_comment | string | "" | Comment for container snapshots. | |
| storage | thumbnail_dir | string | "storage/thumbnails" | Directory for image thumbnail files. |
| guard | max_total_sandboxes | int | 32 | Maximum number of sandboxes allowed in total. |
| max_sandboxes_per_ip | int | 5 | Maximum number of concurrent sandboxes per IP address. | |
| max_sandboxes_per_user | int | 10 | Maximum number of concurrent sandboxes per user. | |
| terminal | max_sessions_per_sandbox | int | 2 | Maximum concurrent terminal sessions per sandbox. |
| idle_timeout_minutes | int | 15 | Close terminal after N minutes of inactivity. | |
| max_duration_minutes | int | 120 | Maximum terminal session duration in minutes. | |
| ssh | enabled | bool | false | Enable the built-in SSH proxy server. |
| port | int | 2222 | Port the SSH proxy listens on. | |
| host | string | "" | SSH host shown to clients. Supports templates: {{.SandboxID}}, {{.ContainerName}}, {{.ContainerID}}, {{.ContainerShortID}}. Empty = derived from sandbox URL. |
The application supports environment variables to override configuration values.
| Environment Variable | Corresponding Config Key |
|---|---|
| LOGGING_LEVEL | logging.level |
| LOGGING_FORMAT | logging.format |
| SERVER_PORT | server.port |
| SERVER_APP_URL | server.app_url |
| DATABASE_HOST | database.host |
| DATABASE_PORT | database.port |
| DATABASE_USER | database.user |
| DATABASE_PASSWORD | database.password |
| DATABASE_NAME | database.name |
| DATABASE_SSLMODE | database.sslmode |
| AUTH_JWT_SECRET | auth.jwt_secret |
| AUTH_JWT_TTL_MINUTES | auth.jwt_ttl_minutes |
| SANDBOX_URL_PREFIX | sandbox.url_prefix |
| SANDBOX_URL_SUFFIX | sandbox.url_suffix |
| SANDBOX_DEFAULT_LIFETIME | sandbox.default_lifetime |
| SANDBOX_MAX_LIFETIME | sandbox.max_lifetime |
| DOCKER_MODE | docker.mode |
| DOCKER_NETWORK | docker.network |
| DOCKER_TRAEFIK_ENABLE | docker.traefik_enable |
| GUARD_MAX_TOTAL_SANDBOXES | guard.max_total_sandboxes |
| GUARD_MAX_SANDBOXES_PER_IP | guard.max_sandboxes_per_ip |
| GUARD_MAX_SANDBOXES_PER_USER | guard.max_sandboxes_per_user |
| TERMINAL_MAX_SESSIONS_PER_SANDBOX | terminal.max_sessions_per_sandbox |
| TERMINAL_IDLE_TIMEOUT_MINUTES | terminal.idle_timeout_minutes |
| TERMINAL_MAX_DURATION_MINUTES | terminal.max_duration_minutes |
| SSH_ENABLED | ssh.enabled |
| SSH_PORT | ssh.port |
| SSH_HOST | ssh.host |
The api includes a built in SSH proxy that routes ssh connections to sandbox containers. Clients connect using the sandbox id encoded in the ssh username:
ssh <username-in-registry-ssh.username>+<sandboxID>@<host> -p <ssh.port>The proxy splits the username on +: the left part is forwarded as the ssh login user to the container, the right part identifies the sandbox. Credentials (username + password) are forwarded transparently to the container's sshd
SSH credentials per image are defined in the registry (api/registry.yml):
images:
- match: "dockware/*"
ssh:
port: 22
username: "dockware"
password: "dockware"Images without an ssh block will not have ssh access. The ssh.host config supports templates for dynamic hostnames:
| Template Variable | Example |
|---|---|
{{.SandboxID}} |
d3bb39e0-d352-493d-... |
{{.ContainerName}} |
sandbox-d3bb39e0-d352-... |
{{.ContainerID}} |
7df8f332e210a4b... (64 chars) |
{{.ContainerShortID}} |
7df8f332e210 (12 chars) |
Copied from .env.example. Controls Docker and database settings:
| Variable | Description | Default |
|---|---|---|
DOCKER_SOCK |
Host path of the Docker daemon socket (bind mounted into the api container) | /var/run/docker.sock |
POSTGRES_USER |
PostgreSQL username | shopshredder |
POSTGRES_PASSWORD |
PostgreSQL password | / |
POSTGRES_DB |
PostgreSQL database name | shopshredder |
WEB_API_URL |
API URL for web frontend | http://localhost:8080 |
This project uses automated CI/CD pipeline and pushes production ready images to Github Packages. The configuration and build options can be found at .github/workflows/release.yml
bab api:devOr manually:
cd api && go run ./cmd/apiDatabase schema changes are managed with Goose using the SQL files in api/internal/database/migrations.
Use Bab to work with migrations:
bab db:migrate
bab db:migrate:status
bab db:migrate:create
bab db:migrate:freshNotes:
bab db:migrateapplies only pending migrations and records them in Goose'sgoose_db_versiontable.bab db:migrate:createcreates a new sequential SQL migration with Goose annotations.bab db:migrate:freshis destructive and intended for local development only.- The production API image includes the
migrateCLI and runsmigrate upautomatically on container start by default. - Set
RUN_MIGRATIONS_ON_START=falseif migrations should be handled separately during deployment.
You can also run the project-local migration CLI directly:
cd api
go run ./cmd/migrate up
go run ./cmd/migrate status
go run ./cmd/migrate create add_user_indexbab web:devOr manually:
cp web/.env.example web/.env # set WEB_API_URL
cd web && pnpm install && pnpm devIn order to provide a Shopware sandbox image, you can not use the default dockware image because it has missing configuration options behind proxies. To avoid getting Mixed-Content and HSTS problems in your browser, you have to extend the dockware image and build a custom sandbox image. Edit the Dockerfile in docker/images/.../Dockerfile and change the Shopware version in the FROM statement. In addition you can add your custom configuration files to the image by copying them into the image.
Then, you can build your new image.
docker build . -t shopshredder-sandbox:6.7.0.0-rc1After that, go to the administration page in the application and add this new image that you just created. Now we have a plain shopware image that can be used for demo and testing purposes.
However, in order to create demonstration images with custom configurations, you have to first start a new sandbox and choose your base image. Then you can open your sandbox in the browser and install plugins, custom themes and configure the entire store as you like.
After that you can create a new snapshot of the running sandbox container. Enter your image name and tag. Congrats, you have created a custom Shopware demo sandbox image. Don't forget to stop the running sandbox container.
This project uses bab as a task runner. Available tasks:
| Command | Description |
|---|---|
bab setup |
Copy example configs for initial setup |
bab dev |
Start infrastructure + API + web dev servers |
bab api:dev |
Run API locally |
bab web:dev |
Run web frontend dev server |
bab docker:up |
Start full stack |
bab docker:infra |
Start infrastructure only (database) |
bab docker:down |
Stop all docker services |
bab docker:destroy |
Stop services and remove volumes |
bab docker:logs |
Follow logs from all services |
bab docker:status |
Show running services |
bab docker:build |
Build all docker images |