{"id":50136185,"url":"https://github.com/jsonbored/penpot-aio","last_synced_at":"2026-05-23T22:02:07.495Z","repository":{"id":359100353,"uuid":"1244435393","full_name":"JSONbored/penpot-aio","owner":"JSONbored","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-20T11:57:04.000Z","size":38,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-20T15:11:08.073Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://aethereal.dev","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JSONbored.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"docs/support-thread-template.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-20T09:04:40.000Z","updated_at":"2026-05-20T11:34:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JSONbored/penpot-aio","commit_stats":null,"previous_names":["jsonbored/penpot-aio"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/JSONbored/penpot-aio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSONbored%2Fpenpot-aio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSONbored%2Fpenpot-aio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSONbored%2Fpenpot-aio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSONbored%2Fpenpot-aio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JSONbored","download_url":"https://codeload.github.com/JSONbored/penpot-aio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSONbored%2Fpenpot-aio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33413623,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T18:09:33.147Z","status":"ssl_error","status_checked_at":"2026-05-23T18:09:31.380Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-23T22:00:49.721Z","updated_at":"2026-05-23T22:02:07.486Z","avatar_url":"https://github.com/JSONbored.png","language":"Python","funding_links":["https://github.com/sponsors/JSONbored","https://ko-fi.com/jsonbored","https://buymeacoffee.com/jsonbored"],"categories":[],"sub_categories":[],"readme":"# penpot-aio\n\n![penpot-aio](https://socialify.git.ci/JSONbored/penpot-aio/image?custom_description=Unraid+CA+AIO+template+and+Docker+image+for+Penpot%2C+the+open-source+design+and+prototyping+platform%2C+with+bundled+PostgreSQL%2C+Redis%2C+Mailpit%2C+exporter%2C+and+MCP.\u0026custom_language=Dockerfile\u0026description=1\u0026font=Raleway\u0026forks=1\u0026issues=1\u0026language=1\u0026logo=https%3A%2F%2Fraw.githubusercontent.com%2FJSONbored%2Fpenpot-aio%2Fmain%2Fassets%2Fapp-icon.png\u0026name=1\u0026owner=1\u0026pattern=Formal+Invitation\u0026pulls=1\u0026stargazers=1\u0026theme=Light)\n\nAn Unraid-first, single-container deployment of [Penpot](https://github.com/penpot/penpot) for people who want the easiest reliable self-hosted install without manually wiring PostgreSQL, Redis, SMTP capture, exporter, MCP, and the upstream compose stack on day one.\n\n`penpot-aio` is opinionated for a predictable beginner install, but it does not hide the real tradeoffs: Penpot is still a heavier multi-service design platform, `PENPOT_PUBLIC_URI` still needs to match the URL users actually visit, and public production use still needs HTTPS, real SMTP, backups, and production-safe flags.\n\n## What This Image Includes\n\n- Penpot frontend served through an Nginx gateway on port `8080`\n- Penpot backend on an internal service port\n- Penpot exporter for render/export flows\n- Penpot MCP server, proxied through the frontend by default\n- Embedded PostgreSQL for the default beginner path\n- Embedded Redis-compatible cache for the default beginner path\n- Embedded Mailpit inbox for local or lab SMTP capture on port `8025`\n- Filesystem object storage under `/appdata/assets` by default\n- Persistent `/appdata` storage for database state, cache state, assets, generated secrets, Mailpit data, and optional overrides\n- Automatic generation and persistence of `PENPOT_SECRET_KEY`, bundled database password, bundled Redis password, and bundled Mailpit UI password when you leave them blank\n- Unraid CA template at [penpot-aio.xml](penpot-aio.xml)\n\n## Beginner Install\n\nIf you want the simplest supported path:\n\n1. Install the Unraid template.\n2. Leave `Web UI Port` and `AppData` at their defaults unless you have a port or path conflict.\n3. Set `Public URL` to the URL users will actually visit, such as `http://tower.local:9001` or your reverse-proxy HTTPS URL.\n4. Start the container and wait a few minutes for first boot.\n5. Open the web UI and create the first account.\n6. If you need local mail capture, open the bundled Mailpit inbox on the advanced `Mailpit UI Port` and read the generated credentials from `/appdata/config/generated.env`.\n\nIf you leave the important secrets blank, the wrapper will:\n\n- generate and persist `PENPOT_SECRET_KEY`\n- generate and persist the bundled PostgreSQL password\n- generate and persist the bundled Redis password\n- generate and persist a bundled Mailpit UI password\n- create and use internal PostgreSQL and Redis-compatible services\n- use filesystem asset storage under `/appdata/assets`\n- use bundled Mailpit for local email capture when external SMTP is blank\n- disable telemetry by default\n\nThe default lab-friendly flags include `disable-email-verification`, `enable-smtp`, `disable-secure-session-cookies`, and `enable-mcp`. Those defaults make first boot easier on a private LAN; they are not the right final posture for a public HTTPS deployment.\n\n## Power User Surface\n\nThis repo is deliberately not a stripped-down wrapper. The generated Unraid template tracks the practical Penpot self-hosted environment surface from upstream config, official compose examples, docs, frontend entrypoint behavior, MCP settings, and AIO-specific defaults. In Advanced View you can:\n\n- move PostgreSQL out of the container with `PENPOT_AIO_ENABLE_INTERNAL_POSTGRES=false` and external `PENPOT_DATABASE_*` settings\n- move Redis or Valkey out of the container with `PENPOT_AIO_ENABLE_INTERNAL_REDIS=false` and `PENPOT_REDIS_URI`\n- keep local Mailpit for lab flows or configure external SMTP for real delivery\n- use filesystem storage by default or configure S3-compatible object storage\n- configure OAuth, OIDC, LDAP, GitHub, GitLab, Google, demo users, and allowed admin accounts\n- tune telemetry, webhooks, file limits, RPC limits, worker/executor behavior, session cookies, rate limits, SSRF protections, and proxy behavior\n- enable or disable the bundled MCP service and optionally publish direct MCP HTTP/WebSocket ports\n- use raw `PENPOT_FLAGS` or the per-flag dropdown controls for known upstream flags\n- use `/appdata/config/extra.env` as a final sanitized key/value escape hatch for rare supported variables\n\nThe wrapper still defaults to the internal bundled services so new Unraid users are not forced into extra containers on day one. External services should be configured intentionally, not half-filled alongside the internal defaults.\n\n## Runtime Notes\n\n- Penpot is a real multi-service stack. Plan for at least 2 CPU cores and 4 GiB RAM, with more for active teams, large files, or concurrent export work.\n- `/appdata` stores generated secrets, PostgreSQL data, cache data, uploaded assets, Mailpit data, logs, and optional override files. Back it up before upgrades or serious use.\n- `PENPOT_PUBLIC_URI` must be correct. Browser flows, links, cookies, callbacks, and reverse-proxy behavior can break when it does not match the URL users actually visit.\n- Public exposure should sit behind a trusted HTTPS reverse proxy. Remove `disable-secure-session-cookies` and `disable-email-verification`, configure real SMTP, and review auth settings before production use.\n- The bundled Mailpit inbox is for local or lab email capture. It is not a production mail relay and does not solve DNS, reputation, SPF, DKIM, DMARC, or deliverability.\n- The bundled database/cache path is meant to make the first install reliable. For more serious production deployments, consider external PostgreSQL, external Redis/Valkey, object storage, and a real backup plan.\n- `/appdata/config/extra.env` is parsed as dotenv-style `KEY=value` data. It is not shell-sourced; shell syntax is not executed, and only supported key prefixes/core runtime keys are accepted.\n\n## Publishing and Releases\n\n- Wrapper releases use the upstream version plus an AIO revision, such as `v2.15.3-aio.1`.\n- Upstream monitoring, release preparation, registry publishing, and catalog sync are owned by `aio-fleet` from `.aio-fleet.yml`.\n- Changelog generation and XML `\u003cChanges\u003e` sync are run centrally by `aio-fleet` during release preparation.\n- `main` publishes `latest`, the pinned upstream version tag, the explicit AIO package tag, and `sha-\u003ccommit\u003e` to Docker Hub.\n- Publish jobs require Docker Hub credentials and push the CA-facing Docker Hub tags directly.\n\nSee [docs/releases.md](docs/releases.md) for the central release process details.\n\n## Validation\n\nRequired local validation is split between app-specific tests and `aio-fleet`:\n\n```bash\npython3 -m venv .venv-local\n.venv-local/bin/pip install -e \"../aio-fleet[app-tests]\"\npython3 scripts/refresh_upstream_inventory.py\npython3 scripts/generate_penpot_template.py --check\n.venv-local/bin/pytest tests/template --junit-xml=reports/pytest-unit.xml -o junit_family=xunit1\n.venv-local/bin/pytest tests/integration -m integration --junit-xml=reports/pytest-integration.xml -o junit_family=xunit1\ncd ../aio-fleet\n.venv/bin/python -m aio_fleet validate-repo --repo penpot-aio --repo-path ../penpot-aio\n.venv/bin/python -m aio_fleet cleanup-repo --repo penpot-aio --repo-path ../penpot-aio --verify\n.venv/bin/python -m aio_fleet sync-catalog --repo penpot-aio --catalog-path ../awesome-unraid --dry-run\n```\n\nThe integration suite builds a Linux amd64 image and boots the full container stack, so it is intentionally more expensive than the unit and XML checks.\n\nThe extended runtime matrix is opt-in and covers external PostgreSQL, external Redis, S3-compatible storage, and external SMTP/Mailpit paths:\n\n```bash\nAIO_RUN_EXTENDED_INTEGRATION=true .venv-local/bin/pytest tests/integration -m extended_integration\n```\n\nCI cost model:\n\n- relevant PRs and `main` pushes run the fast validation layers first\n- Docker-backed integration tests run for build-relevant changes, for `main` release-metadata commits when publish is still in play, and for manual dispatches\n- image publish stays gated behind the integration suite instead of treating skipped integration as acceptable\n- extended provider coverage stays opt-in because it is materially more expensive than the required gate\n\n## Community Apps Sync\n\nThis repo is the source repo. The CA-facing XML and icon should be synced into `JSONbored/awesome-unraid` only after:\n\n1. local validation passes\n2. the image is publishable\n3. the support content is ready\n4. the catalog metadata points at the published Docker Hub image and raw `awesome-unraid/main` assets\n\n## Support\n\n- Repo issues: [JSONbored/penpot-aio issues](https://github.com/JSONbored/penpot-aio/issues)\n- Upstream app: [penpot/penpot](https://github.com/penpot/penpot)\n- Official docs: [help.penpot.app](https://help.penpot.app/)\n- Configuration docs: [Penpot configuration](https://help.penpot.app/technical-guide/configuration/)\n\n## Funding\n\nIf this work saves you time, support it here:\n\n- [GitHub Sponsors](https://github.com/sponsors/JSONbored)\n- [Ko-fi](https://ko-fi.com/jsonbored)\n- [Buy Me a Coffee](https://buymeacoffee.com/jsonbored)\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=JSONbored/penpot-aio\u0026theme=dark)](https://star-history.com/#JSONbored/penpot-aio\u0026Date)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsonbored%2Fpenpot-aio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsonbored%2Fpenpot-aio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsonbored%2Fpenpot-aio/lists"}