39 Commits
Author SHA1 Message Date
Juan Denis b85cc18220 fix: require patched PHP runtimes in WordPress templates 2026-10-23 18:05:08 -04:00
Juan Denis 90c8fb0eac Close the bundled Gitea to the internet and signups
Same fix as the registry's template: Gitea 1.21 was reachable on
every interface with open registration, and a panel's Gitea was
exploited to mine Monero. Bind the web port to 127.0.0.1 behind the
panel's /gitea proxy, disable signups and move to Gitea 1.27.
2026-10-11 17:57:55 -04:00
Juan Denis 0c18aa421f Trace apps through an OpenTelemetry Collector
A new collector template receives OTLP; Attach → Tracing gives an
app the standard OTEL_EXPORTER_OTLP_* variables, and a Jaeger
attached to the collector as its trace store receives the spans.
ServerKit does not instrument apps; it only wires the path. A docker
leg sends a span from an app and finds it in Jaeger.
2026-09-27 22:13:55 -04:00
Juan Denis 4730afa031 Fix Jaeger exiting at start on a fresh volume
The image runs unprivileged and a new named volume at /badger is
root-owned, so badger could not create its directories and every
Jaeger install exited with mkdir /badger/key: permission denied.
It now runs as root inside its own container.
2026-09-27 22:13:54 -04:00
Juan Denis 722072a14b Wire Grafana to Prometheus and Loki by attaching
The Prometheus, Grafana and Loki templates installed but connected
to nothing. A Grafana install now takes Metrics and Logs
attachments: the panel creates the data source through Grafana's
API with the recorded admin login, and a metrics attach also imports
a dashboard of the panel's fleet metrics. An attached app joins the
shared network, so Grafana reaches the source by name.
2026-09-27 21:53:52 -04:00
Juan Denis 776bf7793a Let an installed Prometheus scrape the panel
The metrics endpoint only accepted a PROMETHEUS_TOKEN env var that
almost no install sets, and the Prometheus template's config never
reached its container. The panel now keeps its own scrape token in
an internal vault, hands it to templates as SERVERKIT_METRICS_TOKEN,
and the template ships a prometheus.yml with a serverkit job.
2026-09-27 21:42:18 -04:00
Juan Denis 5e4ebbaf30 Add a queue broker and provision manifest Redis
RabbitMQ joins the catalog with an amqp:// fromService URL. A
manifest service of type redis now installs the Redis engine under
its own name instead of logging declared but not provisioned, so
its consumers' fromService refs bind to it. The bundled index also
gains the Garage entry the storage commit left out.
2026-09-27 21:04:02 -04:00
Juan Denis f23c7a5009 Give each app its own bucket and a scoped key
MinIO's images no longer pull, so object storage is now the Garage
template. Attach storage creates a bucket named for the app and a key
that can read and write only that bucket, keeps the secret in an
internal vault, and wires S3_* and AWS_* env through fromService and
fromSecret. Detach revokes the key and removes the env but keeps the
bucket and its objects. A docker leg proves the scope against a
real Garage.
2026-09-27 20:36:38 -04:00
Juan Denis 954f0dd388 Let apps reference an installed Redis or MinIO
fromService gave full connection details only for managed databases;
a Redis or MinIO sibling resolved to a bare http:// URL on a network
the app could not reach. Engine templates now offer protocol URLs and
their parts, any template can declare properties in a connection:
block, and apps on either side join a shared serverkit-services
network through the managed compose override. Secrets come from the
recorded install variables, never the running container.
2026-09-27 20:08:31 -04:00
Juan Denis 606aa41081 Point postgres templates at the published icon
postgresql.svg was never in the registry's icons/, so serverkit.ai
answered 404 and the catalog fell back to a built-in icon. The logo
the registry publishes is postgres.svg.
2026-09-23 20:23:33 -04:00
Juan DenisandClaude Fable 5 586f556b93 Reference template icons through the serverkit.ai proxy
Follow-up to 025fa0be: keep serverkit.ai as the stable icon host rather
than jsDelivr. The registry repo remains the canonical home of the logo
files; serverkit.ai proxies /imgs/template-icons/ from its raw tree, so
these URLs now resolve for all 210 logos instead of only the legacy
subset the website bundles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 21:28:14 -04:00
Juan DenisandClaude Fable 5 025fa0be7d Point bundled template icons at registry-hosted logos
The offline template bundle carried the same generic stroke-icon data
URIs the registry had, and even the templates with real icons pointed at
serverkit.ai, coupling icon availability to website deploys. Icons now
live in the serverkit-templates repo itself, so reference them through
its jsDelivr mirror. Also fixes pgvector/timescaledb extensions, which
referenced a postgresql.svg that never existed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 21:18:47 -04:00
Juan DenisandClaude Opus 5 a60d63b880 Give the bundled agentsite template its real logo
Matches the registry copy. The bundle is the offline floor, so leaving the
placeholder glyph here would show a different icon to any panel reading it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 00:55:29 -04:00
Juan DenisandClaude Opus 5 ced975aa2b Point the agentsite template at its serverkit.yaml, drop false env requirements
AgentSite now ships a declarative serverkit.yaml, so live inspection of that
repo returns strategy=serverkit. The template's declared hints — the labeled
fallback for when the public repo cannot be reached — still claimed
docker_compose and did not list the file at all, so the fallback described a
different deployment than the real one.

The six provider keys were also all marked required. build_template_hints
passes `required` straight through to the wizard, which stars each one, so the
install screen told people they needed six API keys. AgentSite is
model-agnostic and needs one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 00:45:15 -04:00
Juan DenisandClaude Opus 5 640e7e827e docs(screenshots): recapture, and fix two bugs the capture exposed
Six new sections cover the pages rebuilt this round — the dashboard as it ships,
its edit mode, the widget library, the widget editor, the databases explorer and
the engine catalog drawer. 31/31 sections render.

The capture is a render smoke test, not just a picture, and it earned that here
by surfacing two real bugs that no test could see:

`SearchField` merges its `className` onto its OWN root, so `.skw-lib__search`
IS the `.sk-searchfield` element rather than a wrapper around one. The rule
styling it as a parent matched nothing, leaving the shared `flex: 1 1 240px`
in force — and inside a column-direction filter bar that 240px basis is a
HEIGHT. The widget library's search box was rendering 240px tall.

`GET /auth/me` answers `{user: {...}}`, but Databases read `.role` straight off
the envelope, so `isAdmin` was always false. Every admin got the read-only
console — and with the DDL builder now shipped, would never have seen the button
that runs a CREATE TABLE.

Also carries `postgresql.yaml`, which I left out of the extensions commit.
Without `engine.extensions: true` stock PostgreSQL is not a host for pgvector at
all; the extension tests passed only because the working tree had the change the
commit did not.

Fixture note for whoever edits these next: `/metrics/history` points are NESTED
(`cpu.percent`, `load['1m']`) and carry no network data, `/servers/available` is
a bare array, and `DeployPill` queries `/deployment-jobs` twice and sums — a
single unfiltered payload makes it claim eight running deploys.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 09:59:06 -04:00
Juan DenisandClaude Opus 5 679082bf16 feat(databases): engine extensions, without the silent failure
The third deferred item. An extension installs INTO a running engine rather than
getting its own container, so it lives in its own namespace:
`backend/templates/extensions/<id>.yaml` with a top-level `extension:` block,
discovered by the same operator-wins two-directory scan the app templates use.
Dropping a YAML in makes it available with no code change, and a test pins that.

Not nested inside the engine template, because pgvector applies to any
PostgreSQL-speaking engine rather than to `postgresql.yaml` — nesting would force
duplication per host. Not a third `kind:` in the app catalog either: an
extension has no compose, port or volume and produces no Application, so every
consumer of `list_all_templates` would have had to learn to skip it.

The hard part is not the SQL. `CREATE EXTENSION vector` is valid and fails on
stock `postgres:16` with "could not open extension control file", because that
image does not ship the library. Two layers, and the statement is never sent
speculatively: an extension declares which images provide it, so a listing marks
an instance unsupported BEFORE anything is clicked; then at install
`pg_available_extensions` is queried first and a negative answer is a 409 with a
remedy, not an attempt. The live probe overrules the image name in both
directions — a private `registry.internal/ops/pg-with-vector` is allowed, and a
`pgvector/pgvector` tag that does not actually carry the library is still
refused.

ServerKit does not recreate a container behind the operator's back. The remedy
instead names an engine template that IS capable, found by matching the
extension's images against each engine template's compose — hence
`postgresql-pgvector.yaml`. TimescaleDB deliberately ships no bundled host and
says so rather than implying one exists.

Compatibility also needed correcting mid-build: matching on wire protocol alone
claimed CockroachDB could host pgvector. It answers on pgwire and cannot load a
single extension. Engines opt in with `engine.extensions: true`, which excludes
it without any Python naming it.

Two fixes fell out. `DatabaseService` had no psql twin of `docker_mysql_execute`
— `managed_db_user_service` carried a private copy with a comment saying as
much; there is now one implementation and it delegates. And that twin sets
`ON_ERROR_STOP=1`, without which psql reports SUCCESS for a statement the server
rejected.

57 tests, covering the zero-code-change property, compatibility, the image
problem in both probe directions, admin gating, and refusals that must not
execute anything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 23:44:34 -04:00
Juan DenisandClaude Opus 5 5927e44487 fix(databases): run all twelve engines before claiming they work
The engine templates were written from upstream docs and reviewed carefully, but
only ever read. Every one has now been brought up for real, authenticated
against, and torn down.

CouchDB was broken. A fresh node never created its system databases: `/_all_dbs`
answered `[]`, `_users` did not exist so no non-admin account could ever be
created, and it error-looped on "Missing system database _users". The image
reads only COUCHDB_USER/PASSWORD/SECRET/ERLANG_COOKIE — both
COUCHDB_COUCHDB__SINGLE_NODE and ERL_FLAGS are rejected as unknown_config_value
— so `single_node = true` ships as a local.d config file instead.

Meilisearch and Valkey advertised versions they do not install (1.0 vs the 1.12
that boots; 8.0 vs 8.1.9), caught by comparing the catalog header against what
actually reported for itself.

The method mattered more than the count. Probing auth from INSIDE the container
is not a test and would have passed two engines that were never checked:
postgres initdb writes `host all all 127.0.0.1/32 trust`, so a deliberately
wrong password succeeds on loopback, and the ClickHouse client reads
CLICKHOUSE_PASSWORD out of the container's own environment. Re-run from a remote
source address, both correctly refuse. Every auth assertion here was made from
off-host.

Nine tests cover what can be checked without Docker, led by the one that matters
most: the generated admin password must actually REACH the image. Mongo,
ClickHouse and CouchDB all start happily with authentication disabled when the
password is generated but never passed — silent, and indistinguishable from
working. Also: every ${VAR} resolves, no port binds all interfaces, the catalog
port matches the published one, the declared version is the tag installed, and a
config file can never be rendered over the data volume's mount point (which
would delete persistence without a word).

Verified by reverting each fix and confirming the tests fail with the right
message, then restoring. 67 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 22:51:04 -04:00
Juan DenisandClaude Opus 5 3070353631 feat(databases): install any engine, because an engine is just a template
You could not install a database from ServerKit. The tree's four roots were
literals, only MySQL and PostgreSQL reported real state, and no install path
existed anywhere in the backend.

Rather than add one, this makes a database engine an ordinary app template that
declares a top-level `engine:` block — family, wire protocol, admin user, which
variable holds the password, what it calls a "table". Presence of that block is
the only thing that lists a template in the Databases catalog, and installing it
is the template pipeline that already existed: same deployment job, same
streaming console.

The consequence is the point. Adding CockroachDB is adding a YAML file. So is
adding something we have never heard of — author it locally or sync a template
repo — and the install form still works, because it is generated from the
template's own `variables[]` rather than hand-written per engine. There is no
engine model, no engine table, no engine install mechanism to keep in step.
`test_dropping_a_new_engine_yaml_lists_it` is the design; if it ever needs code
to pass, this went wrong.

Twelve engines ship: postgresql, mysql, mariadb, mongodb, redis, valkey,
cockroachdb, clickhouse, influxdb, neo4j, meilisearch, couchdb. Each pins its
image, binds to loopback, names a data volume, and was checked against the
upstream image's actual environment contract — a wrong variable name is a
container that boots with authentication silently disabled.

Two safety notes worth reading. Engines bind 127.0.0.1 unless explicitly
exposed, and the flag is applied after caller variables so a handcrafted payload
cannot quietly publish one. And CockroachDB single-node runs `--insecure`
because password auth needs a certificate-backed cluster: for engines with no
credentials at all the loopback bind is the only control, so public exposure is
refused outright rather than warned about. A test pins the passwordless list to
exactly cockroachdb, so a future template that drops its password variable
fails loudly instead of opening a hole.

Also surfaced at last: `ManagedDatabase.owner_application_id` has been accepted
by the create endpoints for ages with no UI to set it. Creating a database now
offers "Attach to application".

Deferred deliberately: new-table builder, SQL dump import, engine extensions
(pgvector, TimescaleDB) — each a data-mutation surface deserving its own round.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 20:09:05 -04:00
Juan DenisandClaude Opus 5 da2b77f3d2 feat(templates): tell people whether a template actually fits the server
Deploying checked three things — the name is free, the server row exists, the
directory isn't taken. Nothing asked whether the box could carry the thing, so
a 2 GB app landed on a 1 GB VPS at full speed and the first sign of trouble was
the OOM killer.

Every piece was already here and unconnected: templates describe what they cost
(`requirements: memory / storage`), servers report what they have
(Server.total_memory / total_disk) and what they are using (the newest
ServerMetrics sample). This is the join, answering in the shape a person asks
it — does it fit, will it be tight, or can't we tell?

Advisory on purpose. It reports; it never refuses. An estimate is an estimate,
real usage depends on configuration and traffic, so the operator keeps the
final say and "tight" is a sentence to read rather than a wall to argue with.
A full server still returns valid:true, and a test asserts that so this cannot
quietly become a gate.

Three judgements worth stating:

- The reserve is a floor-and-fraction pair (10% of the box, at least 256 MB RAM
  / 2 GB disk). A bare percentage is wrong at both ends: 10% of 1 GB is
  nothing, 10% of 64 GB is more than most apps need.
- `unknown` outranks `ok`. No recent sample, or a template that declares
  nothing, says so — a confident wrong answer is worse than no answer.
- Free memory comes from psutil's `available`, not `free`: cache and buffers
  are reclaimable, and counting them as used calls every healthy Linux box
  full.

Catalog coverage goes from 52/106 to 106/106. The 54 estimates are each app's
typical idle-to-light-use footprint, taken from the project's own documented
minimum where it publishes one and rounded to the values the existing 52
already use — sonarqube 4 GB because that is its documented heap floor, immich
4 GB for the ML models, prometheus 20 GB because retention dominates, traefik
256 MB.

Surfaced two ways: a capacity block alongside (never inside) `errors` on
validate-install, and a read-only GET the deploy drawer can poll while the
operator is still choosing a target, so the answer updates as they switch
servers instead of waiting for a submit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 15:48:36 -04:00
Juan Denis 0e3bddf30b fix(templates): pin prompture-hub to 0.0.1 (0.0.2 was never published to PyPI) 2026-07-21 23:13:08 -04:00
Juan DenisandClaude Opus 4.8 abe0fbece9 feat(templates): deploy templates as a backend repo-kind catalog entry
Deploy templates were a hardcoded frontend constant (AgentSite, with a
hand-fabricated manifest and an EXAMPLE badge). They now live in the backend
catalog as `kind: repo` YAML entries that blend with the 105 compose templates.

- template schema gains `kind: compose | repo` (absent = compose, so every
  existing template is untouched); repo templates carry a `repo` block with a
  `url` instead of a compose stack
- backend/templates/agentsite.yaml (kind: repo) replaces the JS constant
- list + detail payloads serve `kind`/`repo`; category derivation picks up
  repo templates automatically
- GET /api/v1/templates/<id>/manifest inspects a PUBLIC repo via
  RepositoryManifestService.analyze_public_repo (raw host, no clone, no OAuth)
  and falls back to the template's declared hints, labeled `template-hints`
- index.json + catalog-cert test recognize repo-kind; ratchet floor 2475->2498

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 02:38:46 -04:00
Juan DenisandClaude Opus 4.8 a550f16baf feat: Phase 2 developer experience — build packs, config snapshots, catalog certification
- Build packs / zero-Dockerfile deploys (C1): new BuildpackService detects the
  stack from a cloned repo (Node/Python/Go/PHP/Ruby/Rust/static), produces a
  transparent build plan and a generated Dockerfile, and persists the plan +
  overrides on the Application. POST /api/v1/buildpacks/{detect,generate}; a
  BuildpackPreview shows the detected plan + editable overrides + Dockerfile in
  the create wizard and the app Build tab. Builds on the existing build_method
  plumbing instead of duplicating it.

- Deployment config snapshots + diff engine (C4): ConfigurationService captures
  an immutable, hashed snapshot of resolved config (env keys + masked values,
  domains, image/tag, build method, volumes) at every deploy and rollback; new
  DeploymentSnapshot model + /api/v1/apps/<id>/snapshots[/diff|/restore]. A
  DeploymentTimeline + ConfigDiffModal surface "what changed" and one-click
  restore in the app Deploy tab. Secret values are never serialized.

- Template catalog certification (C5 cont.): a whole-catalog validation test
  proves all 105 declarative templates conform to the documented schema; fixed
  the stale index.json (was 63/105 entries) to list every bundled template.

Migration 030 adds the buildpack columns + deployment_snapshots table. Full
backend suite: 820 passed, 14 skipped; frontend builds clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 18:49:04 -04:00
Juan DenisandClaude Opus 4.8 01871bdc74 feat(services): Phase 3 business & niche utility templates
Adds the heavier business/community tools (larger support surface, gated behind Phases 0-2):

- Customer engagement & signing: chatwoot (rails+sidekiq+pgvector+redis), documenso (+postgres, self-signed cert flow documented).
- Product analytics: metabase (+postgres), posthog (full ClickHouse/Kafka/Zookeeper/MinIO hobby stack, ~4GB RAM).
- Community & bookmarks: nodebb (+postgres), linkding, karakeep (web+chrome+meilisearch).

Roadmap: SERVICES_ROADMAP #21-#23.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 17:22:21 -04:00
Juan DenisandClaude Opus 4.8 6da2933751 feat(services): Phase 2 identity, monitoring, search & networking templates
Fills operational gaps so the catalog feels like a serious self-hosting panel:

- Identity/SSO: authentik (server+worker+postgres+redis, bootstrap admin).
- Monitoring: beszel (hub) and signoz (full OTel/ClickHouse observability stack; OTLP 4317/4318 exposed).
- Search: meilisearch, typesense, searxng (+valkey).
- Notifications: gotify, ntfy.
- Networking/security: wg-easy (WireGuard VPN, fixed UDP 51820) and pihole (DNS sinkhole, fixed 53). Tailscale is host-level and intentionally deferred.

Roadmap: SERVICES_ROADMAP #16-#20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 17:13:24 -04:00
Juan DenisandClaude Opus 4.8 6bb8d10e92 feat(services): Phase 1 media, documents & daily-utility templates
Adds 16 one-click templates across the most-requested self-hosting categories:

- Media/automation: audiobookshelf, calibre-web, and a *arr stack (sonarr, radarr, prowlarr, qbittorrent, jellyseerr) sharing a serverkit-media docker network so they interconnect by container name.
- News/RSS: freshrss, miniflux. Documents: paperless-ngx (+redis +postgres), stirling-pdf, memos.
- Finance: actualbudget, firefly-iii (+postgres). Project mgmt: vikunja, plane (full multi-service stack).
- Brand-neutral, auto-port, generated secrets, lucide icons; icon fallbacks wired in Templates.jsx.

Roadmap: SERVICES_ROADMAP #9-#15.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 17:05:49 -04:00
Juan DenisandClaude Opus 4.8 d00d614501 feat(services): Phase 0 AI/LLM catalog + Prompture Hub anchor
Adds the AI/LLM one-click templates and wires the panel's own AI assistant to a self-hosted Prompture Hub:

- Templates: prompture-hub, ollama-webui, qdrant, chroma, litellm, flowise, langflow, anythingllm, librechat (brand-neutral, auto-port, generated secrets, lucide icons).
- AI provider: new 'prompture-hub' provider routed through Prompture's OpenAI-compatible cachibot driver (hub key + endpoint), so ServerKit AI can call a local hub instead of raw provider keys.
- Featured Prompture Hub + icon fallbacks in the Services UI.

Roadmap: SERVICES_ROADMAP #1-#8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:56:13 -04:00
Juan Denis 986909a955 Surface Docker DBs, add base port & migration fixes
Expose and surface containerised databases and introduce managed app base port control. Backend: add endpoint to list databases across all Docker apps, robustly resolve compose container names, include docker DB user when querying, compute migration needs from live heads and self-heal orphaned alembic_version entries by stamping to head, and add the managed_app_base_port system setting. Template service now honours the managed_app_base_port and WordPress template default HTTP port updated to 8300. Frontend: add react-icons brand icons and DatabaseBrands component, show Docker-hosted DBs under their engine nodes with a docker badge, platform-aware console shortcut label, pass DB user to docker table/query API calls, add API client header merge fix, UI for managing base port in settings, enhanced migration history UI (backup/apply/resync flows, confirm dialog, toasts), and various style tweaks and color additions.
2026-06-06 23:29:22 -04:00
Juan DenisandClaude Opus 4.8 8bc5cc5512 feat(wordpress): one-click create wizard — PHP + page/object cache (#15)
Make WordPressService.create_site a single one-click orchestrator. It now
accepts php_version / enable_page_cache / enable_object_cache and:

- Bakes the chosen PHP version into the INITIAL image tag (concrete
  6.4-php<x.y>-apache) so the site boots on the right PHP with no
  post-create container recreate, then finalizes + _harden_docker_site,
  then best-effort enables page cache (#22) and Redis object cache (#23)
  AFTER `wp core install` (redis already ships in the stack). Cache
  enablement never fails the create — failures degrade to a non-fatal
  warning; the one-time admin password is still surfaced once.

- The live create modal (inline in WordPress.jsx) gains a PHP version
  selector (Default / 8.1 / 8.2 / 8.3) and page-cache / object-cache
  toggles, threaded through createForm -> POST /sites as phpVersion /
  enablePageCache / enableObjectCache (PHP validated server-side).

Mechanism: declare a hidden VERSION template var and switch the image
line to bare ${VERSION} in wordpress.yaml + wordpress-external-db.yaml so
a concrete tag is written at install. This also fixes a latent #24 bug
where the unresolved ${VERSION:-...} literal made set_php_version drop the
WP-core pin; set_php_version now also falls back to the known core for
legacy compose files. No DB migration — PHP/object-cache/SSL read live;
the page-cache flag rides the existing sync_config column.

Deferred: SSL/TLS + custom-domain at create. Managed sites are
http://localhost:PORT containers with no per-site reverse proxy and no
domain attached at create — the same missing public-domain/routing infra
that blocks #21 and that #8 left frontend-only. TLS remains operable
post-create via SiteSSLPanel (#8) once a domain is routed.

Verified: backend py_compile, frontend lint-clean + production build, a
3-lens adversarial review (no blockers), and Docker Hub confirms all
6.4-php8.{1,2,3}-apache tags exist. Not runtime-exercised on a real
Docker host (Windows dev).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 00:12:23 -04:00
Juan DenisandClaude Opus 4.8 6b67271677 feat(wordpress): page cache + per-site Redis object cache (Docker-correct)
Phase C batch 1 — roadmap #22 and #23. The roadmap assumed nginx fastcgi/proxy
cache + host php-fpm, but managed sites are self-contained wordpress:*-apache
containers on localhost:port with no nginx in front — so both are implemented
the Docker-correct way, entirely in-container via the wp_cli bridge.

#22 Full-page cache via the cache-enabler plugin (Apache disk cache), installed
+ activated through wp_cli with WP-aware skip rules (wp-admin/login, logged-in
+ cart/checkout/account cookies, query strings). New routes GET/POST/DELETE
/sites/<id>/page-cache; the enable flag is stored in WordPressSite.sync_config
(no migration); the existing Purge Cache button now also purges the page cache.

#23 Per-site Redis object cache. enable_object_cache ensures a redis service in
the site's compose stack (NEW sites ship redis via the template; EXISTING sites
get a redis service injected into docker-compose.yml + an additive `compose up
-d` with no downtime), then installs the redis-cache plugin (bundled Predis, no
phpredis needed) and points WP at host 'redis'. Status derived live from
`wp redis status`. New routes GET/POST/DELETE /sites/<id>/object-cache; Purge
Cache now also runs `wp redis flush`.

UI: "Enable Page Cache" and "Enable Object Cache" toggles in the site Quick
Actions, reusing the existing .quick-action-btn class (no new/shared SCSS).

Verified: backend boots, all 6 routes register, all 8 service methods load,
template YAML valid; frontend builds; changed JS lints with 0 errors. No DB
migration. (Container-level behavior not runtime-tested — no Docker here.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 23:30:17 -04:00
Juan Denis 3ca6bd23a9 Update template icons and enhance sidebar user menu
Switched all template icon URLs to use local /serverkit.ai/imgs/template-icons/ assets for consistency and reliability. Improved the Sidebar component with a new user context menu featuring theme switching, settings navigation, and logout, along with conditional display of the WordPress pipeline link. Added and updated related styles for the sidebar, user menu, and page headers, and introduced new theme variables for code/terminal backgrounds.
2026-01-27 20:53:57 -05:00
Juan Denis c79e8458c6 Add Flask Hello World debug template
Introduced a new 'Flask - Hello World' template for testing and debugging connectivity, including a sample Flask app with health, debug, and headers endpoints. Updated index.json to register the new template and added 'testing' to the global categories.
2026-01-19 18:07:41 -05:00
Juan Denis f05d056678 Improve port variable handling and add app cleanup CLI
Port variables in templates are now hidden and always auto-generated, never using user-supplied values. The TemplateService's port assignment checks both database and Docker for used ports, and removes obsolete Docker Compose version fields. Adds new CLI commands for cleaning up all applications, performing a factory reset, and listing applications. Minor update to AuthContext to mark setup as complete after registration.
2026-01-19 16:56:57 -05:00
Juan DenisandClaude Opus 4.5 ad20feff86 feat(11): Register WordPress External DB template in index
Add wordpress-external-db to templates registry with:
- Categories: cms, blog, website, development
- Description highlighting dev/prod support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:19:46 -05:00
Juan DenisandClaude Opus 4.5 733705d205 feat(11): Create WordPress External Database template
New template for WordPress with external database support:
- No bundled MySQL container
- Configurable DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
- TABLE_PREFIX for multiple WordPress instances on same database
- Ideal for dev/prod environment sharing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:19:19 -05:00
Juan DenisandClaude Opus 4.5 65ee8ea4cd Fix more templates: ghost, gitea, nextcloud, nginx-proxy-manager
- Convert variables to list format
- Use ${APP_NAME} for container names
- Standardize service names and port variables

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 22:55:21 -05:00
Juan DenisandClaude Opus 4.5 e673be785d Fix template installation and variable handling
- Add APP_NAME as automatic variable for all template installs
- Handle both list and dict formats for template variables
- Update uptime-kuma, portainer, node-app templates with proper format
- Use ${APP_NAME} for container names instead of hardcoded values
- Standardize port variable names to HTTP_PORT

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 22:53:36 -05:00
Juan DenisandClaude Opus 4.5 cab18a32b7 Consolidate templates into backend/templates marketplace
- Removed duplicate root templates/ folder
- Added PHP, Python, Node.js templates to marketplace (YAML format)
- Templates now installable via web UI Templates page
- CLI create-app now points users to web UI
- All 63 templates in one place: backend/templates/

New templates:
- php-app: Custom PHP 8.0-8.3 with Apache
- python-app: Custom Python 3.9-3.12 (Flask/FastAPI/Django)
- node-app: Custom Node.js 18-21 (Express/Next.js)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 22:23:50 -05:00
Juan Denis 87c3a7ee79 Add application templates for multiple popular services
Added YAML templates for a wide range of self-hosted applications, including Authelia, BookStack, Caddy, Code Server, CrowdSec, Directus, Drone CI, Duplicati, Excalidraw, File Browser, GitLab Runner, Grafana, Grav, Home Assistant, Immich, Jaeger, Jellyfin, Jenkins, Jitsi, Keycloak, Loki, Matrix Synapse, Mattermost, MinIO, Mongo Express, Mosquitto, n8n, Navidrome, Netdata, Node-RED, Outline, Payload, pgAdmin, PhotoPrism, phpMyAdmin, Plex, Prometheus, Redis Commander, Registry, Rocket.Chat, Seafile, SonarQube, Strapi, Syncthing, Traefik, Umami, Vault, Vaultwarden, Wiki.js, WordPress, and Zigbee2MQTT. Updated index.json to include all new templates and categories, providing a comprehensive catalog for deployment.
2026-01-18 03:57:44 -05:00
Juan Denis 6d0b84bc91 Add template management API and frontend integration
Introduces backend API endpoints and service logic for managing application templates, including listing, installing, updating, and repository management. Adds several example template YAML files and an index for templates. Updates frontend to support template browsing and installation, including new page, sidebar link, API integration, and styles. Removes the obsolete ROADMAP.md.
2026-01-18 03:42:41 -05:00