Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Agent guidance

Follow [CONTRIBUTING.md](CONTRIBUTING.md) and the current service template.

## Before you edit

- Inspect the target service and its README.
- Confirm ports, commands, volumes, and variables in the image's upstream docs.
- Preserve service-specific exceptions that still apply.
- Keep changes focused on the requested service or documentation.
- Never commit working auth keys, passwords, tokens, or other credentials.

## Verification

Run `docker compose config --quiet` from each changed service directory. When
possible, start the stack and test its main function through the Tailnet.

From the repository root, lint the changed Markdown files. Replace the example paths below as needed:

```sh
rumdl check --config .markdownlint.yml AGENTS.md CONTRIBUTING.md
git diff --check
```

Report the checks you ran. State any checks that credentials, hardware,
permissions, or unavailable tools prevented.
107 changes: 82 additions & 25 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,84 @@
# Contributing to ScaleTail

Thanks for helping expand these Tailscale sidecar examples. Keeping services aligned with the template makes it easier for users to migrate existing Compose stacks without breaking them.

## Adding a new service

1. Copy `templates/service-template` into `services/<service-name>` and rename the compose and README files accordingly.
2. Update `compose.yaml`:
- Keep the Tailscale container named `tailscale-<service>` and the app container named `app-<service>`.
- Set `IMAGE_URL`, `SERVICEPORT`, and any other app variables in `.env`; do not commit secrets or real auth keys.
- Leave `network_mode: service:tailscale` in place and keep `depends_on` using the Tailscale health check.
- Keep the `ports` section commented unless LAN exposure is required; explain why in the README if you expose anything.
- Adjust volumes to match the service, and pre-create bind-mount paths so Docker does not create root-owned folders. (optional)
- If the service needs devices (GPU, render, fuse, etc.) or extra capabilities, add them explicitly and mention them in the README. (optional)
3. Update `"Proxy":"http://127.0.0.1:80"` in `compose.yaml` with the app's actual internal port; it does not consume `.env` values automatically. Remove `TS_SERVE_CONFIG` if Serve/Funnel is not needed.
4. Fill in the service README using the template:
- Briefly describe the app and why Tailscale helps.
- List prerequisites (user in `docker` group, GPU/group membership, devices).
- Call out gotchas: initial admin setup, default credentials, path expectations, required group IDs, or config directory names that must change.
- Clarify MagicDNS/HTTPS steps (`TS_ACCEPT_DNS`), optional 0.0.0.0 port exposure, and any health checks.
- Link to upstream service docs and any official setup videos.
5. Sanity-check the stack with `docker compose config` from the service directory to catch typos and missing variables.

## Updating an existing service

- Keep the sidecar pattern intact (`network_mode: service:tailscale`, health checks, `depends_on`).
- Avoid removing existing volumes or changing container names unless the change is clearly documented in the README.
Thanks for helping improve these Tailscale sidecar examples.

## Add a service

1. Copy the service template from the repository root. Replace `my-service` with your service name:

```sh
cp -R templates/service-template services/my-service
```

This command includes the hidden `.env` file. Use a lowercase directory name.

2. Update `.env` with safe example values.

Set `SERVICE`, `IMAGE_URL`, `SERVICEPORT`, and the application variables.
Never commit a working auth key, password, token, or other credential.

3. Adapt `compose.yaml`.

- Keep the Compose service keys `tailscale` and `application`.
- Name the containers `tailscale-${SERVICE}` and `app-${SERVICE}`.
- Keep `network_mode: service:tailscale` on the application.
- Keep the application's health-based dependency on `tailscale`.
- Add all required persistent volumes.
- Add required devices and capabilities explicitly.

4. Set the Serve proxy to the application's internal port.

The Serve JSON does not read `SERVICEPORT` from `.env`. Keep runtime variables
escaped, such as `$${TS_CERT_DOMAIN}`.

Keep the `ports` block commented for Tailnet-only access. Document any LAN
port you expose. Remove the Serve configuration when the service does not use
Tailscale Serve.

5. Add a health check that the application image can run.

Prefer an application endpoint or an upstream health command. Remove the
application health check when no reliable check exists. Keep the Tailscale
health check.

6. Complete the service README.

Document prerequisites, persistent paths, setup steps, ports, Tailnet access,
and service-specific exceptions. Link to the upstream documentation.

7. Add the service to the correct category in the root `README.md`.

Keep the entries in that category alphabetized.

## Update a service

- Read the service README and Compose file before you make changes.
- Preserve the shared network namespace and Tailscale dependency.
- Preserve persistent volumes unless you document a safe migration.
- Use `${VARIABLE}` for Compose interpolation, not `$(VARIABLE)`.
- Update the service README when ports, paths, setup, or behavior change.
- Update the root service list when you add, remove, or rename a service.

Preserve valid service-specific exceptions.

## Verify your change

Run Compose validation from each changed service directory:

```sh
docker compose config --quiet
```

This command does not prove that the application works.

When possible, start the stack and confirm:

- Tailscale becomes healthy and joins the Tailnet.
- The application starts and is reachable through the Tailnet.
- The application's main function works.
- Persistent storage and documented LAN access work, when applicable.

## Submit a pull request

Follow the pull request template. Report the checks you ran and any checks you
could not run.