feat(release): prepare first public preview

This commit is contained in:
Magent release tooling
2026-09-22 15:17:22 +12:00
parent 76b2b8d879
commit 27ff894f68
29 changed files with 610 additions and 103 deletions
+1
View File
@@ -5,6 +5,7 @@
!Dockerfile
!.dockerignore
!LICENSE
!THIRD_PARTY_NOTICES.md
!backend/
!backend/requirements.txt
!backend/app/
+1
View File
@@ -7,6 +7,7 @@
*.png binary
*.jpg binary
*.jpeg binary
*.webp binary
*.gif binary
*.ico binary
*.pdf binary
+40
View File
@@ -0,0 +1,40 @@
---
name: Bug report
about: Report reproducible behavior that looks wrong
title: "[Bug] "
labels: ""
---
## What happened?
<!-- Describe the visible problem. -->
## What did you expect?
<!-- Describe the expected result. -->
## How can we reproduce it?
1.
2.
3.
## Environment
- Magent version/tag:
- Container image digest, if applicable:
- Installation method (Compose, Portainer, docker run, native):
- Host OS and CPU architecture:
- Browser and version:
- Reverse proxy, if applicable:
- Connected app and version involved:
## Sanitized diagnostics
<!-- Paste the smallest relevant error/log excerpt. Redact private addresses and user data. -->
- [ ] I searched existing issues and the troubleshooting guides.
- [ ] I reproduced this on the current public preview.
- [ ] I removed passwords, tokens, API keys, cookies, email addresses, private URLs and personal data.
- [ ] I did not attach an `.env`, database, backup or generated secrets file.
- [ ] This is not a security vulnerability. Security reports follow `SECURITY.md`.
+26
View File
@@ -0,0 +1,26 @@
---
name: Feature request
about: Suggest an improvement to Magent
title: "[Feature] "
labels: ""
---
## Problem
<!-- Who has this problem, and what are they trying to do? -->
## Desired outcome
<!-- Describe the user-visible result. -->
## Current workaround
<!-- How do you handle it today? -->
## Relevant integration
<!-- If this needs another app, include its name, version and public API docs. -->
## Additional context
<!-- Mockups and synthetic examples are welcome. Remove private data. -->
@@ -0,0 +1,29 @@
---
name: Installation help
about: Ask for help with a documented installation path
title: "[Install] "
labels: ""
---
## Goal
<!-- What are you trying to install, and where? -->
## Method and environment
- Installation guide followed:
- Host OS and CPU architecture:
- Docker/Compose/Portainer/Python/Node versions, as applicable:
- Browser-facing URL scheme (`http` or `https`; redact private hostnames if needed):
- Reverse proxy, if applicable:
## Where it stopped
<!-- Include the exact command/step and sanitized output. -->
## Checks already tried
- [ ] I checked the matching troubleshooting table.
- [ ] I confirmed the container/service health and retained the same data path.
- [ ] I removed credentials, tokens, cookies, private URLs and personal data.
- [ ] I did not attach an `.env`, database, backup or generated secrets file.
+17
View File
@@ -0,0 +1,17 @@
## What and why
<!-- Explain the user problem and the change. -->
## Validation
<!-- List exact commands/checks run and any skipped platform checks. -->
- [ ] Backend tests pass or are not affected.
- [ ] Frontend tests, lint, format, typecheck and build pass or are not affected.
- [ ] Documentation and changelog are updated where needed.
- [ ] New behavior has regression coverage.
- [ ] No credentials, user data, databases, backups or private deployment details are included.
## Compatibility
<!-- Note database, configuration, container, API or upgrade effects. -->
+36
View File
@@ -0,0 +1,36 @@
# Changelog
This file records public Magent releases. The in-application changelog contains
the shorter user-facing highlights.
## Unreleased
- No unreleased changes recorded.
## 0.1.0-preview.1 — 2026-09-22
First public preview.
### Included
- Guided first-install setup for the administrator, application URL and optional integrations.
- Request discovery, submission and status tracking across Seerr and Arr services.
- Jellyfin playback links, issue reporting and repair follow-up.
- Jellystat viewing insights, monthly reports and optional email recaps.
- Local/Jellyfin sign-in, invitations, account linking and feature controls.
- Encrypted configuration/database backups with staged, restart-only restore.
- Docker Compose, Docker CLI, Portainer, native Linux and foreground setup guides.
- Hardened non-root container defaults and a documented release smoke harness.
### Known limits
- The published image is validated for Linux/amd64 only.
- One writable SQLite instance and one backend worker are supported; HA is not.
- Native Linux services have static systemd validation, not broad distribution certification.
- This preview does not promise an LTS window or security-response SLA.
### Upgrade note
Existing installations must retain their data mount and signing/encryption keys.
Create an encrypted backup, record the running image digest, and follow the
[upgrade guidance](docs/DOCKER.md#updates-and-rollback).
+21
View File
@@ -0,0 +1,21 @@
# Repository guide
Magent combines a FastAPI backend, Next.js frontend and SQLite database. Read
`CONTRIBUTING.md` before changing code and `docs/INSTALLATION.md` before changing
deployment behavior.
## Important paths
- `backend/app/`: API, integrations, setup, persistence and background work.
- `frontend/app/`: application routes and interface components.
- `backend/tests/` and frontend `*.test.*`: synthetic regression coverage.
- `compose.yml`: public prebuilt-image deployment.
- `Dockerfile`: pinned multi-stage production build.
## Working rules
- Never read, commit or print real `.env`, database, backup or credential data.
- Keep SQLite to one backend worker and one writable application instance.
- Preserve origin checks, CSP nonces, non-root execution and persistent key/data paths.
- Add regression tests and run the checks in `CONTRIBUTING.md`.
- Use synthetic fixtures; do not call live media services from tests.
+23
View File
@@ -0,0 +1,23 @@
# Community Code of Conduct
Magent's community should be practical, welcoming and safe for people with
different backgrounds and levels of experience.
## Expected behavior
- Be respectful and specific when discussing code, ideas or mistakes.
- Assume good intent while accepting corrections and evidence.
- Give useful context and protect other people's privacy.
- Welcome questions without mocking a person's experience level.
- Keep feedback about the work, not the person.
Harassment, threats, discrimination, sexualized attention, deliberate exposure
of private information, and repeated disruptive behavior are not acceptable.
Maintainers may edit or remove contributions and temporarily or permanently
restrict participation when needed to protect the community. Non-sensitive
conduct concerns can be raised through the issue tracker. The public preview
does not yet publish a monitored private conduct-reporting channel; do not put
private evidence or personal information in a public issue.
This code applies in project spaces and when representing the project elsewhere.
+65
View File
@@ -0,0 +1,65 @@
# Contributing to Magent
Thanks for helping improve Magent. Small, reviewable changes with a clear reason
are the easiest to test and merge.
## Before opening an issue
- Use [SUPPORT.md](SUPPORT.md) to choose the right report type.
- Search existing issues and read the relevant installation guide.
- Remove credentials, tokens, email addresses, database content and private URLs.
- Use [SECURITY.md](SECURITY.md) for vulnerabilities; do not publish exploit details.
## Development setup
Use Python 3.14 and Node.js 24. Follow
[the foreground development guide](docs/LOCAL_DEVELOPMENT.md), use synthetic
data, and never connect tests to someone else's services.
## Quality checks
Backend:
```sh
python -m venv .venv
. .venv/bin/activate
pip install -r backend/requirements-dev.txt
python -m unittest discover -s backend/tests -p 'test_*.py'
python scripts/check_environment_docs.py
```
Frontend:
```sh
cd frontend
npm ci
npm test
npm run lint
npm run format:check
npm run typecheck
npm run build
```
Container changes should also pass both isolated smoke modes:
```sh
docker build -t magent:review .
bash scripts/ci_container_smoke.sh magent:review
MAGENT_SMOKE_MANAGED=true bash scripts/ci_container_smoke.sh magent:review
```
The smoke harness creates disposable containers, networks and volumes. Do not
aim it at a live instance or reuse a production volume.
## Pull requests
1. Base public work on the `release` branch.
2. Keep each pull request focused and explain the user-visible reason.
3. Add or update tests for behavior changes.
4. Update documentation and `CHANGELOG.md` when behavior or setup changes.
5. State exactly which checks ran and any platform limits or skipped checks.
6. Do not commit generated builds, `.env` files, logs, databases, backups or secrets.
By contributing, you agree that your contribution is licensed under the project's
[MIT License](LICENSE). Participation must follow the
[Code of Conduct](CODE_OF_CONDUCT.md).
+8 -2
View File
@@ -54,6 +54,8 @@ RUN node --version
ARG MAGENT_UID=1000
ARG MAGENT_GID=1000
ARG MAGENT_VERSION=0.1.0-preview.1
ARG MAGENT_REVISION=unknown
RUN addgroup -g ${MAGENT_GID} magent \
&& adduser -D -u ${MAGENT_UID} -G magent -s /sbin/nologin magent \
&& install -d -o magent -g magent -m 0700 /app/data \
@@ -76,12 +78,16 @@ COPY --chown=magent:magent --from=frontend-builder /frontend/.next/static /app/f
COPY --chown=magent:magent --from=frontend-builder /frontend/public /app/frontend/public
COPY docker/supervisord.conf /etc/supervisor/conf.d/magent.conf
COPY LICENSE /usr/share/licenses/magent/LICENSE
COPY --chown=magent:magent LICENSE /usr/share/licenses/magent/LICENSE
COPY --chown=magent:magent THIRD_PARTY_NOTICES.md /usr/share/licenses/magent/THIRD_PARTY_NOTICES.md
COPY --from=frontend-builder /licenses /usr/share/licenses/magent/frontend
LABEL org.opencontainers.image.title="Magent" \
org.opencontainers.image.description="Self-hosted media requests, issues and viewing insights" \
org.opencontainers.image.licenses="MIT"
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.source="https://git.amslabs.net/Rephl3x/Magent-Public" \
org.opencontainers.image.version="${MAGENT_VERSION}" \
org.opencontainers.image.revision="${MAGENT_REVISION}"
USER magent:magent
+108 -75
View File
@@ -1,78 +1,111 @@
# Magent
Self-hosted media requests, viewing stats and issue management for Jellyfin,
Seerr, Sonarr, Radarr and related services. Magent combines a Python/FastAPI API,
a Next.js frontend and SQLite. Run the prebuilt non-root container or install
the Python and Node.js services directly—Portainer is optional.
Magent is a self-hosted home for media requests, viewing insights and issue
follow-up. It sits in front of Jellyfin, Seerr, Sonarr, Radarr and related apps,
then turns their technical state into a clearer experience for the people using
your server.
## Install
**Public preview:** `0.1.0-preview.1` · [Source code](https://git.amslabs.net/Rephl3x/Magent-Public) ·
[Docker Hub](https://hub.docker.com/r/rephl3xnz/magent) · [MIT license](LICENSE)
Start with the [installation guide](docs/INSTALLATION.md) to choose a method:
![Magent's first-run setup wizard](docs/images/setup-wizard.webp)
| Method | Instructions |
| --- | --- |
| Docker Compose or `docker run` | [Docker installation](docs/DOCKER.md) |
| Portainer | [Single-file stack](docs/PORTAINER.md) |
| Linux without Docker | [Native install and systemd services](docs/NATIVE_INSTALL.md) |
| Windows/macOS/Linux foreground | [Source installation and development](docs/LOCAL_DEVELOPMENT.md) |
Magent does not store or stream media, replace your existing applications, or
provide content. You bring and operate those services; Magent connects to them.
For a fresh **Docker Compose** install, download [compose.yml](compose.yml) into
its own deployment directory and run:
## Why Magent?
Media automation is powerful, but its status messages are written for operators.
Magent gives users one place to request something, understand what is happening,
see when it is ready, report a problem and follow the response.
- Search for and submit movie or TV requests through Seerr.
- Follow a request across approval, Arr monitoring, download and Jellyfin availability.
- Open ready titles in Jellyfin and report playback or library problems.
- View private Jellystat-powered viewing insights and monthly reports.
- Offer local or Jellyfin sign-in, invite-only registration and per-user features.
- Manage integrations, users, branding, notifications and diagnostics from the UI.
- Export an encrypted backup of configuration, SQLite data and optional artwork.
## Current scope
- The published container is validated on **Linux/amd64**.
- Magent is a single-instance application using one writable SQLite database. It
is not an HA, Kubernetes or multi-replica deployment.
- Native Windows foreground operation has been smoke-tested. Linux systemd files
are statically validated; macOS instructions are reviewed but not runtime-tested.
- This is an early public release. Pin an immutable image tag or digest, retain
backups, and test upgrades before using them on your main instance.
See [release notes](CHANGELOG.md) and [installation support boundaries](docs/INSTALLATION.md#platform-and-support-boundaries).
## Quick start with Docker Compose
Docker Compose is the recommended first installation. Create an empty directory,
download the public Compose file, and start Magent:
```sh
curl --fail --location --output compose.yml \
https://git.amslabs.net/Rephl3x/Magent-Public/raw/branch/release/compose.yml
docker compose -f compose.yml -p magent pull
docker compose -f compose.yml -p magent up -d --wait --wait-timeout 120
docker compose -f compose.yml -p magent exec --user magent magent \
python -m app.container_bootstrap setup-token
```
PowerShell:
```powershell
Invoke-WebRequest -Uri 'https://git.amslabs.net/Rephl3x/Magent-Public/raw/branch/release/compose.yml' -OutFile compose.yml
docker compose -f compose.yml -p magent pull
docker compose -f compose.yml -p magent up -d --wait --wait-timeout 120
docker compose -f compose.yml -p magent ps
docker compose -f compose.yml -p magent exec --user magent magent python -m app.container_bootstrap setup-token
```
Keep that directory/project name and its persistent volume unchanged for updates.
This uses `rephl3xnz/magent:latest` with no environment variables, local source
build or Dockerfile. Portainer users can paste the same file into a Docker
Standalone stack instead. Native users follow their separate guide for explicit
environment configuration and service management.
Open `http://SERVER_IP:3000/setup`, enter the console-only token and confirm the
browser-facing URL. Then create the first administrator and connect the apps you
use. Optional integrations can be skipped. The managed image creates and retains
its own private keys; this path needs no `.env` or Dockerfile.
**Image availability:** the managed-install image is published on Docker Hub.
Only Linux/amd64 has been validated. `latest` is mutable; record the resolved
image digest before updating, or pin an immutable release tag.
If you cloned the repository, the optional helper exposes the same operations:
`./setup.sh check`, `./setup.sh install`, and `./setup.sh token`. Read a script
before running it; the documented Compose commands remain the canonical path.
1. Wait for the container to become healthy and retrieve the token using the
command above (or the Portainer console instructions in its guide).
2. Open the Docker host's address on port 3000. Confirm the browser-facing URL
in setup and use the token to create the first administrator.
The **Get setup token** button shows the console instructions and lets you
copy the command; it never reveals the token to public visitors.
3. Connect your apps, choose preferences and finish setup. Optional apps can
be skipped. Save an encrypted backup afterwards.
For public access, configure DNS and HTTPS before creating the administrator.
Do not forward the plain HTTP port directly to the internet.
Keep the Compose security block unchanged. Database storage is fixed at
`/app/data/magent.db` and API docs are disabled in managed installs. CORS and
cookie security follow the confirmed URL. Use HTTPS before public access.
## Other installation methods
See [all installation methods](docs/INSTALLATION.md),
[all environment options](docs/ENVIRONMENT.md),
[backup and restore](docs/installation-and-recovery.md) and
[advanced installation/upgrades](docs/PUBLIC_RELEASE.md).
Existing installations must retain their original data volume and signing/
encryption keys; this fresh-install template is not an automatic migration.
| Method | Guide |
| --- | --- |
| Docker Compose | [Complete Docker guide](docs/DOCKER.md#docker-compose) |
| Docker CLI without Compose | [`docker run` guide](docs/DOCKER.md#docker-cli-without-compose) |
| Portainer | [Paste-and-deploy stack](docs/PORTAINER.md) |
| Build the container from source | [Source-build override](docs/DOCKER.md#build-the-container-from-source) |
| Native Linux | [Python/Node and systemd](docs/NATIVE_INSTALL.md) |
| Windows, macOS or Linux foreground | [Local/source installation](docs/LOCAL_DEVELOPMENT.md) |
## Build and test
Start with the [installation overview](docs/INSTALLATION.md) if you are unsure.
The [environment reference](docs/ENVIRONMENT.md) documents every supported
variable, while [backup and recovery](docs/installation-and-recovery.md) covers
portable exports, offline snapshots and safe restore.
The source tree contains everything needed to build the application:
### Existing installations
Keep the same Compose project name, data mount and signing/encryption keys. The
fresh-install named volume is not an automatic migration of an existing bind
mount. Record your working image digest and make an encrypted backup before an
upgrade. Never use `docker compose down -v` on data you want to keep.
## Build and test from source
```sh
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent-Public.git
cd Magent-Public
docker compose -f compose.yml -f compose.build.yml -p magent up -d --build
```
For a disposable verification run, without touching an existing installation:
```sh
docker build -t magent:review .
bash scripts/ci_container_smoke.sh magent:review
MAGENT_SMOKE_MANAGED=true bash scripts/ci_container_smoke.sh magent:review
```
Unit checks require Python 3.14 and Node 24:
The full quality gate uses Python 3.14 and Node.js 24:
```sh
python -m venv .venv
@@ -86,37 +119,37 @@ npm test
npm run lint
npm run format:check
npm run typecheck
npm run build
```
On Windows, activate `.venv\Scripts\Activate.ps1` instead. Do not point tests
at live services or use production credentials.
On Windows, use `.venv\Scripts\Activate.ps1`. Tests must use synthetic data and
must never point at live media services.
## How it is organised
## Project layout
- `backend/app/routers/`: authenticated API endpoints and administration.
- `backend/app/clients/`: media-service clients; `services/`: request states,
synchronisation, notifications, setup and encrypted backups.
- `backend/app/db.py` and `schema_migrations.py`: SQLite persistence/migrations.
- `frontend/app/`: pages and shared interface components; `frontend/proxy.ts`:
browser security headers and request nonces.
- `backend/app/`: FastAPI routes, service clients, request state, authentication,
setup, notifications and encrypted backups.
- `frontend/app/`: Next.js pages, shared UI, account portal and administration.
- `backend/tests/` and frontend `*.test.*`: synthetic regression tests.
- `Dockerfile` and `docker/`: multi-stage build and process supervision.
- `compose.yml`: prebuilt-image install; `compose.build.yml`: source override.
- `deploy/native/`: example Linux service units and backend/frontend configuration.
- `compose.yml`: prebuilt-image install; `compose.build.yml`: source-build override.
- `deploy/native/`: example Linux service units and private configuration templates.
- `docs/`: installation, environment, HTTPS, backup, upgrade and rollback guidance.
Requests are cached from Seerr, joined to collector/download/library evidence,
normalised into a user-facing state and displayed by the frontend. App settings
are stored in SQLite; sensitive settings are encrypted with installation-specific
keys. Integrations are optional and are configured through the setup wizard.
The `release` branch is a deliberately small public export. It excludes private
deployment automation, credentials, runtime data and internal Git history.
This `release` branch intentionally excludes internal deployment scripts,
environment files, runtime data, development reports and prior Git history.
It contains no workflow that automatically deploys or publishes an image.
## Help, feedback and contributions
## Contributing and security
- Read [SUPPORT.md](SUPPORT.md) before opening an installation or bug report.
- See [CONTRIBUTING.md](CONTRIBUTING.md) for development and pull-request checks.
- Report security concerns using [SECURITY.md](SECURITY.md); never post secrets or
exploit details in a public issue.
- Community participation follows [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
Keep changes focused, add regression tests and run the checks above. Never
commit tokens, database exports, backups or real user information.
See [SECURITY.md](SECURITY.md) for reporting guidance and deployment precautions.
Magent was developed through an iterative, AI-assisted workflow and then checked
with automated regression tests, isolated container smoke tests and a sanitized
public-release pass. Treat generated code like any other code: inspect it, test
it and report anything that does not make sense.
Licensed under [MIT](LICENSE). Third-party dependency licences remain applicable.
Magent is licensed under the [MIT License](LICENSE). Dependencies and base-image
components retain their own licenses; see [third-party notices](THIRD_PARTY_NOTICES.md).
+10 -5
View File
@@ -4,11 +4,16 @@
Do not post passwords, access tokens, encryption keys, database exports, backup
files or live exploit details in public issues, discussions or container logs.
Use the repository hosting platform's private vulnerability-reporting feature
if the release owner has enabled it. Otherwise contact the maintainer privately
through the platform where you obtained this release before sending sensitive
details. This repository does not currently advertise a dedicated reporting
address; the release owner must establish one before a broad public launch.
Non-sensitive security hardening reports may be filed at
https://git.amslabs.net/Rephl3x/Magent-Public/issues/new after removing all
deployment details and secrets. The public preview does not yet publish a
monitored confidential-reporting channel. Do not put embargoed vulnerabilities,
live exploits or sensitive evidence in a public issue. If a report cannot be
made safely in public, retain it until a private contact is listed here.
Reports are handled on a best-effort basis. The project does not promise a
specific response time or security-support window. The newest public preview is
the only version considered for security fixes unless a release note says otherwise.
Include the image tag/digest, affected version, a minimal reproduction using
synthetic data, and the security impact. Remove deployment credentials and
+31
View File
@@ -0,0 +1,31 @@
# Support
Magent is an early public release maintained on a best-effort basis. There is no
paid support or guaranteed response time.
## Start here
- Installation choice: [docs/INSTALLATION.md](docs/INSTALLATION.md)
- Docker and Compose: [docs/DOCKER.md](docs/DOCKER.md)
- Portainer: [docs/PORTAINER.md](docs/PORTAINER.md)
- Native Linux: [docs/NATIVE_INSTALL.md](docs/NATIVE_INSTALL.md)
- Configuration: [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md)
- Backup and restore: [docs/installation-and-recovery.md](docs/installation-and-recovery.md)
## Ask for help or report a problem
Use the matching issue template at
https://git.amslabs.net/Rephl3x/Magent-Public/issues/new.
Include the Magent version/tag and image digest, CPU architecture, installation
method, browser, exact reproduction steps, expected result and sanitized logs.
Say whether the problem survives a normal restart. Never attach `.env` files,
databases, backups, generated secret files, API keys, passwords, access tokens,
private URLs or personal viewing data.
Feature requests should describe the problem and intended user, not only a
proposed implementation. Integration requests should link to the upstream
application's public API documentation.
For a vulnerability, follow [SECURITY.md](SECURITY.md) instead of opening a
detailed public report.
+27
View File
@@ -0,0 +1,27 @@
# Third-party notices
Magent's original source is licensed under the [MIT License](LICENSE). Third-party
software and assets retain their own copyright and license terms.
The exact JavaScript dependency graph and resolved versions are recorded in
`frontend/package-lock.json`. Production runtime packages include Next.js,
React, React DOM, Sharp and their transitive dependencies. Their license terms
come from the installed package metadata and license files, not from fields in
the lockfile. The release build collects discoverable production package
license and notice files under `/usr/share/licenses/magent/frontend`.
The exact direct Python versions are recorded in `backend/requirements.txt` and
`docker/requirements-runtime.txt`. Python package metadata and license files are
installed with those packages and remain subject to their respective terms.
The release container also contains components from its pinned Python, Node.js
and Alpine base images. Those components are not relicensed by Magent. The image
includes this notice, Magent's MIT license, Node.js's license, installed Python
package license files, discoverable production frontend license/notice files,
and any license files supplied by the Alpine packages in the runtime image under
`/usr/share/licenses`.
Before redistributing a modified image, regenerate and review its software bill
of materials and preserve every applicable license, copyright and notice file.
Lockfiles are the version inventory; this summary is not a replacement for the
complete license texts supplied by each dependency.
+5 -2
View File
@@ -1,2 +1,5 @@
BUILD_NUMBER = "0803262237"
CHANGELOG = '2026-09-19|Initial minimal release source snapshot'
BUILD_NUMBER = "0.1.0-preview.1"
CHANGELOG = """2026-09-22|First public preview
2026-09-22|Guided setup for Docker, Portainer and native installs
2026-09-22|Encrypted backup and staged restore
2026-09-22|Requests, viewing insights, invites and issue follow-up"""
+2 -2
View File
@@ -515,7 +515,7 @@ class SiteInfoTests(unittest.TestCase):
"site_banner_tone": "warning",
"site_banner_background_color": "#123ABC",
"site_banner_border_color": "red",
"site_login_message": "Use your Grizzlyflix account to sign in.",
"site_login_message": "Use your ExampleFlix account to sign in.",
})
with patch.object(site_router, "get_runtime_settings", return_value=runtime):
@@ -523,7 +523,7 @@ class SiteInfoTests(unittest.TestCase):
self.assertEqual(info["banner"]["backgroundColor"], "#123abc")
self.assertIsNone(info["banner"]["borderColor"])
self.assertEqual(info["login"]["message"], "Use your Grizzlyflix account to sign in.")
self.assertEqual(info["login"]["message"], "Use your ExampleFlix account to sign in.")
class SiteSettingValidationTests(unittest.IsolatedAsyncioTestCase):
+1 -1
View File
@@ -41,7 +41,7 @@ class IssueAcceptanceTests(TempDatabaseMixin, unittest.IsolatedAsyncioTestCase):
content = email.await_args.kwargs
self.assertEqual(content["subject"], f"Ready to try again? Magent issue #{item['id']}")
self.assertIn("affected content in Jellyfin", content["body_text"])
self.assertNotIn("grizzlyflix", content["body_html"].lower())
self.assertNotIn("exampleflix", content["body_html"].lower())
self.assertIn("YES — it works", content["body_html"])
self.assertIn("NO — still broken", content["body_html"])
self.assertIn(f"/issues/confirm/{item['id']}#yes", content["body_html"])
+3 -3
View File
@@ -93,7 +93,7 @@ class NewsletterConsentTests(NewsletterFixture, unittest.IsolatedAsyncioTestCase
rendered = sender.call_args.args[1]
self.assertEqual(rendered['subject'], 'Confirm your Magent newsletter subscription')
self.assertIn('NEW IN YOUR LIBRARY', rendered['body_html'])
self.assertNotIn('grizzlyflix', rendered['body_html'].lower())
self.assertNotIn('exampleflix', rendered['body_html'].lower())
self.assertNotIn('Arrival', rendered['body_html'])
url = re.search(r'https://[^\s]+', rendered['body_text']).group(0)
self.assertEqual(urlsplit(url).path, '/newsletter-subscription')
@@ -393,7 +393,7 @@ class NewsletterDeliveryTests(NewsletterFixture, unittest.IsolatedAsyncioTestCas
self.assertEqual(draft['intro'], custom_intro)
def test_generic_email_template_preserves_custom_subject_and_intro(self):
custom_subject = 'Grizzlyflix weekend discoveries'
custom_subject = 'ExampleFlix weekend discoveries'
custom_intro = 'Welcome to our own <media> community.'
rendered = template.render(
{**content(), 'subject': custom_subject, 'intro': custom_intro}, {},
@@ -406,7 +406,7 @@ class NewsletterDeliveryTests(NewsletterFixture, unittest.IsolatedAsyncioTestCas
self.assertIn('Welcome to our own &lt;media&gt; community.', rendered['body_html'])
self.assertIn('Watch on Jellyfin', rendered['body_html'])
self.assertIn('Explore Jellyfin', rendered['body_html'])
self.assertNotIn('grizzlyflix', rendered['body_html'].lower())
self.assertNotIn('exampleflix', rendered['body_html'].lower())
async def test_weekly_worker_collects_once_and_delivers_to_confirmed_subscriber(self):
now = datetime.now(timezone.utc)
+4 -4
View File
@@ -64,7 +64,7 @@ container in either case, not a native Windows-container or macOS application.
### 1. Save the deployment file
Create a new directory for this installation and save the release branch's
[raw compose.yml](https://git.amslabs.net/Rephl3x/Magent/raw/branch/release/compose.yml)
[raw compose.yml](https://git.amslabs.net/Rephl3x/Magent-Public/raw/branch/release/compose.yml)
there. Keep your customized copy for future operations instead of overwriting
it when updating. You need only this file for the prebuilt image.
@@ -73,7 +73,7 @@ Linux, macOS or WSL:
```sh
mkdir magent-install
cd magent-install
curl --fail --location --output compose.yml https://git.amslabs.net/Rephl3x/Magent/raw/branch/release/compose.yml
curl --fail --location --output compose.yml https://git.amslabs.net/Rephl3x/Magent-Public/raw/branch/release/compose.yml
```
PowerShell:
@@ -81,7 +81,7 @@ PowerShell:
```powershell
New-Item -ItemType Directory -Path magent-install
Set-Location magent-install
Invoke-WebRequest -Uri 'https://git.amslabs.net/Rephl3x/Magent/raw/branch/release/compose.yml' -OutFile compose.yml
Invoke-WebRequest -Uri 'https://git.amslabs.net/Rephl3x/Magent-Public/raw/branch/release/compose.yml' -OutFile compose.yml
```
Alternatively, open the raw link in your browser and save the plain text as
@@ -236,7 +236,7 @@ It requires the full source tree and Docker build support; the prebuilt-image
installation does not. Use a separate checkout directory:
```sh
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent.git Magent-source
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent-Public.git Magent-source
cd Magent-source
docker compose -f compose.yml -f compose.build.yml -p magent config --quiet
docker compose -f compose.yml -f compose.build.yml -p magent build magent
+4
View File
@@ -238,6 +238,8 @@ consumer; builder values and supervisor values are not user-editable app setting
| `PYTHONUNBUFFERED` | Image: `1` | Flush Python stdout/stderr without buffering. |
| `MAGENT_UID` | Build argument: `1000` | Image runtime user's UID. Not a runtime environment switch; rebuilding with a different UID also requires matching volume/tmpfs ownership. |
| `MAGENT_GID` | Build argument: `1000` | Image runtime user's GID; same ownership caveat as UID. |
| `MAGENT_VERSION` | Build argument: `0.1.0-preview.1` | OCI image version label. Release builds set this to their public version; it does not change runtime data. |
| `MAGENT_REVISION` | Build argument: `unknown` | OCI image source-revision label. Release builds set this to the full source commit. |
## Manual Compose and test tooling
@@ -249,6 +251,8 @@ verification tools, not the zero-input public Compose install.
| `MAGENT_IMAGE` | Required by `docker-compose.hub.yml` | Explicit published image tag/digest for manual-secret installations. |
| `MAGENT_BIND_ADDRESS` | `127.0.0.1` | Manual template frontend bind address. |
| `MAGENT_HTTP_PORT` | `3000` | Manual template frontend host port. |
| `MAGENT_COMPOSE_FILE` | `compose.yml` | Optional `setup.sh` Compose filename override. Use a trusted local file. |
| `MAGENT_PROJECT_NAME` | `magent` | Optional `setup.sh` Compose project name. Keep it stable to retain the same named volume. |
| `PYTHON_BIN` | `python3` | Interpreter used by the backend quality gate. |
| `MAGENT_IMAGE_MAX_MB` | `350` | Container smoke-test unpacked image size budget in MiB. |
| `MAGENT_SMOKE_MANAGED` | `false` | Test generated managed secrets when true, or synthetic manual keys when false. |
+2 -2
View File
@@ -15,7 +15,7 @@ connect a development checkout to production credentials/databases.
Linux/macOS (Bash/zsh):
```sh
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent.git magent
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent-Public.git magent
cd magent
python3.14 -m venv .venv
.venv/bin/python -m pip install -r backend/requirements.txt
@@ -24,7 +24,7 @@ python3.14 -m venv .venv
Windows (PowerShell, with Python's `py` launcher installed):
```powershell
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent.git magent
git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent-Public.git magent
Set-Location magent
py -3.14 -m venv .venv
& .\.venv\Scripts\python.exe -m pip install -r backend\requirements.txt
+1 -1
View File
@@ -47,7 +47,7 @@ sudo useradd --system --user-group --create-home --home-dir /var/lib/magent --sh
sudo install -d -o magent -g magent -m 0755 /opt/magent
sudo install -d -o root -g root -m 0700 /etc/magent
sudo install -d -o magent -g magent -m 0700 /var/lib/magent/data
sudo -u magent git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent.git /opt/magent
sudo -u magent git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent-Public.git /opt/magent
sudo -u magent git -C /opt/magent rev-parse HEAD
sudo -u magent python3.14 -m venv /opt/magent/.venv
sudo -u magent /opt/magent/.venv/bin/python -m pip install -r /opt/magent/backend/requirements.txt
+96
View File
@@ -0,0 +1,96 @@
# Reddit launch post
For `r/vibecoding`, use the **Vibe-Coded Projects** category/flair and retain the
build-process section below. The community's current self-promotion guidance says
project posts need educational detail about tools, workflow and lessons rather
than only a link. Recheck its rules immediately before posting. Add sanitized
screenshots if available; never show real users, domains, libraries, service URLs
or credentials.
## Suggested title
I vibe-coded Magent: a self-hosted request, stats and issue portal for Jellyfin stacks
## Alternative titles
- Magent is ready for testers — Docker, Portainer and native installs
- Sharing Magent: one place for media requests, viewing stats and issue follow-up
## Post
Hey everyone,
I’ve been vibe-coding a self-hosted project called **Magent**, and its first
public preview is ready for people to inspect, install and break:
https://git.amslabs.net/Rephl3x/Magent-Public
Magent is the user-facing layer I wanted around a Jellyfin media stack. It brings
requests, request progress, viewing stats and issue follow-up into one place,
while Jellyfin, Seerr, Sonarr, Radarr and the other connected apps keep doing the
jobs they already do.
What it currently includes:
- Search for and submit movie or TV requests through Seerr
- A plain-English request timeline across approval, Arr, downloads and Jellyfin
- “Watch now” links when something is available
- Issue reporting and repair follow-up
- Personal Jellystat viewing insights and monthly reports
- Local/Jellyfin sign-in, invitations and per-user feature controls
- Encrypted backup and restore for configuration and the SQLite database
It does **not** provide, store or stream media. You need to operate and connect
your own services.
Docker Compose is the recommended setup, but the repository also documents
Portainer, plain `docker run`, source-built containers, native Linux/systemd and
foreground Windows/macOS/Linux installs. A fresh managed Docker install creates
its own private keys and setup token, then walks you through the administrator
and app connections in the browser.
Docker image: https://hub.docker.com/r/rephl3xnz/magent
This is deliberately labelled a public preview. The container is currently
validated on Linux/amd64, Magent expects one writable SQLite instance, and it is
not presented as an HA/Kubernetes deployment. The repo documents HTTPS, reverse
proxies, origins/cookies, backups, upgrades and rollback rather than pretending
those details disappear.
The project grew through an iterative AI-assisted/vibe-coding workflow, followed
by regression tests, isolated container smoke tests and a separate sanitization
pass for the public repository. I’m sharing the source under MIT because I want
the implementation to be inspectable, not just the result.
### How I built it
My workflow was much closer to directing a small engineering loop than writing
one giant prompt. I described a user problem, had Codex work across the FastAPI,
Next.js and Docker layers, then reviewed the result in a running Beta instance.
Screenshots and real failure reports became the next round of requirements.
The useful discipline was making every vibe pass leave evidence behind. Backend
behavior got regression tests, interface changes got browser checks, and the
container got a disposable smoke harness covering fresh setup, login, security
headers, assets, encrypted backup/restore, restart and recreation. I also used
the ECC Codex plugin as a structured security/release review rather than treating
“it works on my stack” as a release gate.
The biggest release lesson was that a Git branch is not a privacy boundary. My
first idea was a sanitized public branch alongside private Beta/Prod branches.
Before launch I caught that every branch and old tag in a public repository is
still public, so I split the three-commit sanitized export into its own repository.
That was more valuable than another round of UI polish.
The most useful early feedback would be:
- where setup assumes too much knowledge
- installation steps that are unclear or wrong on your platform
- integrations that behave differently on another stack
- request, stats or issue flows that confuse real users
- backup or restore problems
Please use synthetic examples and sanitized logs in public reports—no tokens,
databases, backup files or private service details.
Repository: https://git.amslabs.net/Rephl3x/Magent-Public
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

+3 -3
View File
@@ -16,7 +16,7 @@ describe("portable default branding", () => {
expect(html).toContain("Welcome to our library");
expect(html).toContain("A custom message");
expect(html).toContain("Local help");
expect(html).not.toMatch(/grizzlyflix/i);
expect(html).not.toMatch(/exampleflix/i);
expect(html).not.toContain(">Beta<");
});
@@ -25,13 +25,13 @@ describe("portable default branding", () => {
expect(html).toContain("MAGENT");
expect(html).toContain("Your media member portal");
expect(html).not.toMatch(/grizzlyflix/i);
expect(html).not.toMatch(/exampleflix/i);
});
it("explains the Jellyfin integration without a deployment-specific service name", () => {
const html = renderToStaticMarkup(<HowItWorksPage />);
expect(html).toContain("Jellyfin is where you watch them.");
expect(html).not.toMatch(/grizzlyflix/i);
expect(html).not.toMatch(/exampleflix/i);
});
});
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "magent-frontend",
"version": "0803262237",
"version": "0.1.0-preview.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "magent-frontend",
"version": "0803262237",
"version": "0.1.0-preview.1",
"dependencies": {
"next": "16.3.5",
"react": "19.2.4",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "magent-frontend",
"private": true,
"version": "0803262237",
"version": "0.1.0-preview.1",
"scripts": {
"dev": "next dev",
"build": "next build",
Executable
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env sh
set -eu
compose_file="${MAGENT_COMPOSE_FILE:-compose.yml}"
project_name="${MAGENT_PROJECT_NAME:-magent}"
usage() {
echo "Usage: ./setup.sh check|install|status|token|logs"
echo "Run this script from a directory containing the public compose.yml."
}
compose() {
docker compose -f "$compose_file" -p "$project_name" "$@"
}
case "${1:-}" in
check)
docker version >/dev/null
docker compose version >/dev/null
compose config --quiet
echo "Docker and compose.yml are ready."
;;
install)
compose config --quiet
compose pull
compose up -d --wait --wait-timeout 120
compose ps
echo "Open http://SERVER_IP:3000/setup, then run: ./setup.sh token"
;;
status)
compose ps
;;
token)
compose exec --user magent magent python -m app.container_bootstrap setup-token
;;
logs)
compose logs --tail=150 magent
;;
*)
usage
exit 2
;;
esac