Compare commits

...
12 Commits
Author SHA1 Message Date
tiennm99 f38a3a2871 docs: revise install location and naming rules
Workspace services install tools into the home volume unless the package
is more than a binary. Prefer official images and treat upstream compose
files as a starting point. Name volumes <service>-<content> and networks
<main service>-network.
2026-10-06 17:09:38 +07:00
tiennm99 d889338306 fix(alloy): drop docker log lines older than Loki accepts
loki.source.docker resumes from a one-second position and Docker's since
is inclusive, so each restart re-reads a container's last logged second.
For idle containers those lines are older than 7 days and Grafana Cloud
Loki rejects the batch with 400 timestamp too old. Drop them before
loki.write; Loki would not have stored them anyway.
2026-10-06 16:56:46 +07:00
tiennm99 feb6f035c8 fix(alloy): mount /run/udev for diskstats device properties
node-exporter's diskstats collector reads udev device properties from
/run/udev/data; without the mount it logs an error and drops those labels.
2026-10-06 16:50:22 +07:00
tiennm99 fc85962f45 fix: restore HOST override in zsh workspace services
Coolify injects HOST=0.0.0.0 and zsh's prompt reads $HOST instead of the
real hostname, so hostname: alone shows user@0. Set HOST=${SERVICE_HOSTNAME}
again in code-server, code-server-lsio and paseo.
2026-10-06 16:45:13 +07:00
tiennm99 56111e9219 fix(alloy): pass the Grafana token as GCLOUD_RW_API_KEY
Fleet Management's self-monitoring pipelines read the token from that name;
without it their remote-write fails with 401 invalid token.
2026-10-06 16:45:13 +07:00
tiennm99 422eab8499 chore: drop HOST overrides, move known issue to docs, tidy comments and gitignores
- Remove HOST=${SERVICE_HOSTNAME} from code-server, code-server-lsio and paseo; hostname: alone sets the name
- Move SERVICE_HOSTNAME to the top of their .env.example to match compose order
- Drop the openclaw ARM64 Chromium note from its README; docs/openclaw covers it
- List CUSTOM_USER in webtop's setup step
- Trim reasoning from diun and paseo comments
- Delete stale gitea and gitea-mirror .gitignore files
- Add TODO.md for remaining naming and README issues
2026-10-06 16:32:32 +07:00
tiennm99 042d6bd6c0 chore: drop container labels from cadvisor, require webtop CUSTOM_USER, trim env template comments 2026-10-06 16:19:14 +07:00
tiennm99 4c5c6ed17e chore: name couchbase's service after its image 2026-10-06 16:05:42 +07:00
tiennm99 e4c74ef5cd chore: align alloy, diun and couchbase with repo conventions
alloy: move to latest tags (no moving major tag upstream), trim comments to what each line does.
diun: order .env.example like compose.yml.
couchbase: add .env.example, drop the version key, explain the published ports.
2026-10-06 16:03:37 +07:00
tiennm99 0637a02051 chore: drop container_name from couchbase 2026-10-06 15:57:40 +07:00
tiennm99 272db135b7 chore: drop container_name from alloy and traffmonetizer 2026-10-06 15:57:10 +07:00
tiennm99 98b0924ca7 chore: drop traffmonetizer version key, document its restart policy, add alloy .env.example 2026-10-06 15:55:36 +07:00
24 changed files with 196 additions and 88 deletions

No files matched your search

+26 -10
View File
@@ -17,21 +17,36 @@ suffix naming its source — `code-server-lsio` for LinuxServer's code-server
so both can coexist. The suffix is a directory name only, forced by the
conflict; it is not a name to copy anywhere else.
Inside `compose.yml`, service, volume and network names follow the upstream
project's official Docker guide. Where the guide gives none, the main service
takes the image's own name (`code-server`, not `code-server-lsio`), and a
supporting container may be named for its role instead — `db`, `database`,
`cache` and the like.
Prefer each tool's official image, for the main service and for every
supporting container alike. Upstream's official compose file or Docker guide
is a starting point, not a spec: adapt it to the conventions in this file
rather than copying its layout and names as they are.
Inside `compose.yml`, a service is named after its image — `code-server`, not
`code-server-lsio`. A supporting container may instead be named for its role —
`db`, `database`, `cache` and the like — so the software behind it can be
swapped without renaming: Redis for Valkey, MySQL for MariaDB, or one SQL
database for PostgreSQL.
A volume is named `<service>-<what it holds>`, after the service that mounts it
and its mount point or meaning — `code-server-home`, `code-server-workspace`,
`db-data`. A network is named after the main service: `code-server-network`.
## Installing software in an image
Follow the upstream project's own documented install method, or the one the
community has settled on. In order of preference: the vendor's signed package
repository, the vendor's official tarball or install script, then a well-known
community installer. Do not hand-roll a download, and do not take a stale
community has settled on. Do not hand-roll a download, and do not take a stale
distro package just because `apt install` is shorter — check what version it
actually gives you first.
Where it gets installed depends on the kind of service. In a workspace service
(see below), install tools into a location that survives a redeploy — the
container user's home volume, such as `~/.local/bin` — not into the image. The
exception is a system package that is more than a single binary — shared
libraries, a daemon, anything that hooks into `/etc` or the system paths. That
goes in the image, through the system package manager. Every other service
installs into the image.
## Comments in compose files, Dockerfiles and scripts
This holds for every file in a service directory, not just the compose file.
@@ -151,7 +166,7 @@ collapse and the existing grouping stands.
`.env.example` follows its compose file's order. The names differ — one
`PASSWORD` can feed several container variables, and `SERVICE_HOSTNAME` feeds
`HOST` — so each entry sits where the first compose entry that reads it sits.
`hostname:` and `HOST` — so each entry sits where the first compose entry that reads it sits.
Reordering a compose file means reordering the `.env.example` with it.
## Deployment target
@@ -183,7 +198,8 @@ adding hardening or convention that the platform already provides.
when a service does not declare one, and keeps the declared value when it does;
Dokploy does not inject anything, so in its default compose mode an omitted
policy leaves the container down after a crash or a host reboot. Setting it is
correct on both.
correct on both. `traffmonetizer` sets `restart: always` on purpose, to be
restarted as often as possible.
## Secrets
+23
View File
@@ -0,0 +1,23 @@
# TODO
## Names that differ from the upstream Docker guide
Renaming a volume on a running deployment orphans its data, so each rename
needs a volume migration (the `migrate-service` skill), not just an edit.
- [ ] `owncloud` — upstream names its volumes `oc_files`, `mysql` and `redis`;
here they are `owncloud-data`, `owncloud-mysql-data` and
`owncloud-redis-data`.
- [ ] `litellm` — upstream's database service is `db` with volume
`postgres_data`; here it is `postgres` with `pg-data`.
- [ ] `openclaw` — upstream's service is `openclaw-gateway`; here it is
`openclaw`. Upstream uses bind mounts, so the volume names are free.
- [ ] `gitea` — Gitea's install guide names the app service `server`; here it
is `gitea`. Confirm against the current guide before renaming.
## README contradiction
- [ ] `code-server-lsio/README.md` says the `universal-docker` mod adds `abc` to
the Docker socket's group, so `docker` works without `sudo`.
`webtop/README.md` says `abc` is not in that group and must use `sudo`.
Both use the same mod; check which is true and fix the other.
+23
View File
@@ -0,0 +1,23 @@
# Copy to .env and fill in. Never commit .env.
#
# cp .env.example .env
# Container hostname, and the Loki/Prometheus `instance` label. Set per host.
ALLOY_HOSTNAME=alloy
# Grafana Fleet Management endpoint, agent id (set per host) and user id.
REMOTECFG_URL=
REMOTECFG_ID=alloy
REMOTECFG_USER=
# Prometheus remote-write endpoint and user id.
PROM_URL=
PROM_USER=
# Loki push endpoint and user id.
LOKI_URL=
LOKI_USER=
# Cloud Access Policy token with metrics:write, logs:write and
# fleet-management:read. Serves remotecfg, Prometheus and Loki.
GRAFANA_TOKEN=
+24 -7
View File
@@ -7,11 +7,9 @@ Management.
One container runs both the `node_exporter` (host) and `cadvisor` (container)
collectors. A second, tiny container proxies a read-only slice of the Docker
API to it. The Alloy config is embedded inline via Compose `configs:`, so
there is no `config.alloy` on disk. There is no `.env.example` either: the
nine variables are exported before `docker compose up`.
there is no `config.alloy` on disk.
Both containers have fixed names,
`container_name: alloy` and `alloy-dockerproxy`, and `dockerproxy` publishes
`dockerproxy` publishes
`127.0.0.1:2375` — Alloy runs with host networking, so it has no compose
network to reach the proxy over.
@@ -20,7 +18,7 @@ network to reach the proxy over.
| Source | Component | Notes |
|---|---|---|
| Host metrics | `prometheus.exporter.unix` | CPU, memory, load, disk I/O, filesystem, network, uname, boot time, systemd, vmstat, sockstat — the default collector set minus `ipvs/btrfs/infiniband/xfs/zfs` |
| Container metrics | `prometheus.exporter.cadvisor` | CPU, memory, fs usage/limit, network, `last_seen` |
| Container metrics | `prometheus.exporter.cadvisor` | CPU, memory, fs usage/limit, network, `last_seen`. Docker labels are not copied onto the series (`store_container_labels = false`): Coolify gives its containers 50–80 labels, which pushes series past Grafana Cloud's 60-label limit and gets them rejected |
| Container logs | `loki.source.docker` | All running containers, labeled `container`, `stream`, `instance` |
| Journal logs | `loki.source.journal` | systemd journal, labeled `unit`, `boot_id`, `transport`, `level` |
| File logs | `loki.source.file` | `/var/log/syslog`, `/var/log/messages`, `/var/log/*.log` |
@@ -29,7 +27,12 @@ network to reach the proxy over.
Metric filtering copies the `keep`-lists from the upstream Grafana Cloud
integrations verbatim ([Linux Node](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-linux-node/#metrics),
[Docker](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-docker/#metrics)).
Logs are unfiltered.
Logs are unfiltered, except that container log lines older than 168h are
dropped before they are sent. Grafana Cloud Loki rejects anything older than
7 days, and `loki.source.docker` re-reads a container's last second of logs
on every restart (its saved position has one-second precision), so an idle
container's last lines would otherwise come back as a `400 timestamp too old`
error on every redeploy. Nothing Loki would have accepted is dropped.
## Environment
@@ -45,12 +48,18 @@ All nine are required; `docker compose up` fails fast if any is unset.
| `LOKI_URL` / `LOKI_USER` | Loki push endpoint and user id |
| `GRAFANA_TOKEN` | One Cloud Access Policy token, scopes `metrics:write` + `logs:write` + `fleet-management:read` |
`GRAFANA_TOKEN` is also passed into the container as `GCLOUD_RW_API_KEY`.
Fleet Management's auto-generated `self_monitoring_*` pipelines read the token
from that fixed name; without it their remote-write gets an empty password and
Grafana Cloud answers `401 invalid token`, so the collector shows no health
data in Fleet Management.
Find the values under Grafana Cloud → your stack → **Details** on each data
source, and under Fleet Management. The same token serves `remotecfg`,
Prometheus and Loki basic-auth.
```bash
export ALLOY_HOSTNAME=example-host REMOTECFG_ID=example-host ...
cp .env.example .env # then fill in the values
docker compose up -d
```
@@ -127,6 +136,7 @@ the disclosure one.
| `/sys:/sys:ro` | node-exporter and cadvisor cgroups |
| `/:/rootfs:ro` | filesystem collector, via `rootfs_path` |
| `/dev/disk/:/dev/disk:ro` | node-exporter diskstats device labels |
| `/run/udev:/run/udev:ro` | node-exporter diskstats udev device properties (`/run/udev/data`) |
| `/var/lib/docker:ro` | cadvisor container metadata |
| `/var/log:/var/log:ro` | `loki.source.journal` and `loki.source.file` |
| `/etc/machine-id:ro` | Stable host id for the journal reader |
@@ -134,3 +144,10 @@ the disclosure one.
`dockerproxy` mounts `/var/run/docker.sock:ro` and nothing else.
## Version pinning
Both images use `latest`. Neither project publishes a moving major tag:
`grafana/alloy` ships only exact `v1.x.y` tags, and `tecnativa/docker-socket-proxy`
only exact `v0.x.y` tags (its bare `0` tag is a stale leftover). `latest` is the
closest equivalent, so new releases arrive on the next redeploy.
+27 -20
View File
@@ -1,12 +1,11 @@
services:
alloy:
image: grafana/alloy:v1.16.1
container_name: alloy
image: grafana/alloy:latest
restart: unless-stopped
hostname: ${ALLOY_HOSTNAME:?required}
network_mode: host # node_exporter netdev/netstat sees real host interfaces (eth0…) not veth
network_mode: host
cap_drop: [ALL]
cap_add: [DAC_OVERRIDE] # read host files owned by other uids: journal, /rootfs, /var/log
cap_add: [DAC_OVERRIDE]
security_opt:
- no-new-privileges:true
mem_limit: 2g
@@ -23,28 +22,29 @@ services:
LOKI_URL: ${LOKI_URL:?required}
LOKI_USER: ${LOKI_USER:?required}
GRAFANA_TOKEN: ${GRAFANA_TOKEN:?required}
GCLOUD_RW_API_KEY: ${GRAFANA_TOKEN:?required}
volumes:
- alloy-data:/var/lib/alloy/data
- /proc:/rootproc:ro
- /sys:/sys:ro
- /:/rootfs:ro
- /dev/disk/:/dev/disk:ro
- /run/udev:/run/udev:ro
- /var/lib/docker/:/var/lib/docker:ro
- /var/log:/var/log:ro # journal + syslog/messages/*.log for the Linux-Node integration
- /etc/machine-id:/etc/machine-id:ro # stable host id for systemd journal reader
- /var/log:/var/log:ro
- /etc/machine-id:/etc/machine-id:ro
configs:
- { source: alloy_config, target: /etc/alloy/config.alloy }
command: 'run --storage.path=/var/lib/alloy/data /etc/alloy/config.alloy'
dockerproxy:
image: tecnativa/docker-socket-proxy:v0.5.0
container_name: alloy-dockerproxy
image: tecnativa/docker-socket-proxy:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 64m
pids_limit: 64
environment: # the API sections cadvisor and the log tailer read; POST stays revoked
environment:
CONTAINERS: 1
NETWORKS: 1
IMAGES: 1
@@ -112,7 +112,7 @@ configs:
prometheus.exporter.unix "integrations_node_exporter" {
disable_collectors = ["ipvs", "btrfs", "infiniband", "xfs", "zfs"]
// Read host filesystems via bind mounts instead of the container namespace.
// Read host filesystems through the /rootfs and /rootproc bind mounts.
rootfs_path = "/rootfs"
procfs_path = "/rootproc"
@@ -136,10 +136,7 @@ configs:
forward_to = [prometheus.relabel.integrations_node_exporter.receiver]
}
// Keep only the metrics enumerated under "Metrics" in the upstream
// Grafana Cloud Linux Node integration page (157 metrics, verbatim).
// The recording-rule output `instance:node_num_cpu:sum` is computed
// server-side by Grafana Cloud's ruler — not shipped from here.
// Keep only the Grafana Cloud Linux Node integration's metric list.
prometheus.relabel "integrations_node_exporter" {
forward_to = [prometheus.remote_write.metrics_service.receiver]
@@ -166,8 +163,7 @@ configs:
forward_to = [loki.relabel.integrations_node_exporter.receiver]
}
// File-based logs from the Linux-Node integration: syslog/messages/*.log.
// On systemd hosts, rsyslog often mirrors journald — see README "What it collects".
// File logs from the Linux Node integration: syslog, messages, *.log.
local.file_match "integrations_node_exporter_files" {
path_targets = [{
__address__ = "localhost",
@@ -179,7 +175,7 @@ configs:
forward_to = [loki.relabel.integrations_node_exporter.receiver]
}
//JOURNAL
// Journal logs.
declare "journal_module" {
argument "forward_to" {
optional = false
@@ -216,8 +212,9 @@ configs:
}
prometheus.exporter.cadvisor "integrations_cadvisor" {
docker_only = true
docker_host = "tcp://127.0.0.1:2375"
docker_only = true
store_container_labels = false
docker_host = "tcp://127.0.0.1:2375"
}
discovery.relabel "integrations_cadvisor" {
targets = prometheus.exporter.cadvisor.integrations_cadvisor.targets
@@ -279,7 +276,17 @@ configs:
loki.source.docker "logs_integrations_docker" {
host = "tcp://127.0.0.1:2375"
targets = discovery.docker.logs_integrations_docker.targets
forward_to = [loki.write.grafana_cloud_loki.receiver]
forward_to = [loki.process.logs_integrations_docker.receiver]
relabel_rules = discovery.relabel.logs_integrations_docker.rules
refresh_interval = "5s"
}
// Drop container log lines older than Grafana Cloud Loki accepts.
loki.process "logs_integrations_docker" {
forward_to = [loki.write.grafana_cloud_loki.receiver]
stage.drop {
older_than = "168h"
drop_counter_reason = "too_old"
}
}
+3 -4
View File
@@ -2,6 +2,9 @@
#
# cp .env.example .env
# Container hostname, also passed in as HOST -- the name zsh's prompt shows.
SERVICE_HOSTNAME=code-server-lsio
# Web UI login password. Required.
# Also used for SUDO_PASSWORD inside the container.
# Generate one with: openssl rand -base64 24
@@ -11,9 +14,5 @@ PASSWORD=
GIT_NAME=
GIT_EMAIL=
# Container hostname, also passed in as HOST -- the name zsh's prompt shows.
# Not named HOSTNAME: the deploying shell's own HOSTNAME would override it.
SERVICE_HOSTNAME=code-server-lsio
# Name of the installed web app.
# PWA_APPNAME=code-server
+3 -4
View File
@@ -2,6 +2,9 @@
#
# cp .env.example .env
# Container hostname, also passed in as HOST -- the name zsh's prompt shows.
SERVICE_HOSTNAME=code-server
# Web UI login password. Required.
# Generate one with: openssl rand -base64 24
PASSWORD=
@@ -10,9 +13,5 @@ PASSWORD=
GIT_NAME=
GIT_EMAIL=
# Container hostname, also passed in as HOST -- the name zsh's prompt shows.
# Not named HOSTNAME: the deploying shell's own HOSTNAME would override it.
SERVICE_HOSTNAME=code-server
# Name shown in the title bar and welcome page.
# CODE_SERVER_APP_NAME=code-server
+5
View File
@@ -0,0 +1,5 @@
# Copy to .env and fill in. Never commit .env.
#
# cp .env.example .env
# No variables: the cluster is configured in the admin console on port 8091.
+3 -2
View File
@@ -1,11 +1,12 @@
# couchbase
[Couchbase Server](https://www.couchbase.com), single node, defined in
`compose.yml` with `container_name: db`.
`compose.yml`.
## Networking
Publishes its ports on the host:
Clients connect to Couchbase directly on its ports, not through a domain on the
proxy, so it publishes them on the host:
| Ports | Purpose |
| --- | --- |
+1 -4
View File
@@ -1,9 +1,6 @@
version: '3'
services:
db:
couchbase:
image: couchbase
container_name: db
ports:
- "8091-8097:8091-8097"
- "9123:9123"
+1 -1
View File
@@ -1,6 +1,6 @@
DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=true
DIUN_NOTIF_TELEGRAM_TOKEN=
DIUN_NOTIF_TELEGRAM_CHATIDS=
DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=true
DIUN_WATCH_SCHEDULE=0 0 * * *
# DIUN_WATCH_WORKERS=10
# DIUN_WATCH_JITTER=30s
+1 -1
View File
@@ -21,7 +21,7 @@ services:
depends_on:
- dockerproxy
# Read-only slice of the Docker API. POST is revoked by default in this image.
# Read-only slice of the Docker API.
dockerproxy:
image: tecnativa/docker-socket-proxy:latest
restart: unless-stopped
@@ -0,0 +1,37 @@
# Docker logs re-sent on restart
Applies to `alloy/compose.yml`. Checked against Alloy v1.20.1.
## Symptom
Every time Alloy restarts, `loki.write` logs one rejected batch:
```
final error sending batch, no retries left, dropping data ... status=400
13 errors like: entry for stream '{container="coolify-realtime", ...}'
has timestamp too old: 2026-09-18T17:00:51Z, oldest acceptable timestamp is: ...
```
The same containers, the same timestamps and the same counts show up on every
restart.
## Cause
`loki.source.docker` saves each container's read position as a Unix timestamp
in **seconds** (`internal/component/loki/source/docker/tailer.go`,
`t.positions.Put(..., ts.Unix())`). On start it asks the Docker API for logs
`since` that second, and Docker includes the second itself. So every restart
re-reads every line written in the container's last logged second.
For a busy container those lines are recent, and Loki silently discards them
as exact duplicates. For an idle container whose last line is more than 7 days
old, Grafana Cloud Loki rejects them with `timestamp too old` instead.
Positions are kept in the `alloy-data` volume, so they are not being lost.
Re-reading that last second is simply how the component works.
## Fix
`loki.process "logs_integrations_docker"` sits between `loki.source.docker` and
`loki.write` and drops lines older than `168h` with `stage.drop`. Those lines
would be rejected by Loki anyway, so nothing that would have been stored is
lost. The drops are counted under `loki_process_dropped_lines_total{reason="too_old"}`.
+1
View File
@@ -51,6 +51,7 @@ Where official mixin dashboards exist they're tier-2 corroboration:
| `prometheus.exporter.cadvisor` (`docker_only = true`) | Docker integration page |
| `prometheus.relabel "integrations_cadvisor"` (`keep` allowlist of 16 metrics) | Docker integration page → [Metrics](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-docker/#metrics) section, verbatim |
| `discovery.docker` + `loki.source.docker` (job/instance/container/stream) | Docker integration page → log scraping |
| `loki.process "logs_integrations_docker"` (drop lines older than 168h) | Local addition, not upstream. Drops only what Loki rejects anyway; see [docker-logs-resent-on-restart.md](docker-logs-resent-on-restart.md) |
## What "follow upstream" means in practice
-3
View File
@@ -1,3 +0,0 @@
gitea-mirror/
.env
purge.py
-3
View File
@@ -1,3 +0,0 @@
gitea/
.env
purge.py
+1 -3
View File
@@ -2,13 +2,11 @@
#
# cp .env.example .env
# Bearer token for the gateway API and dashboard. MUST NOT be blank -- a blank
# token serves the agent gateway, and the tools its agents can run, to anyone.
# Bearer token for the gateway API and dashboard. Required.
# Generate one with: openssl rand -hex 16
GOCLAW_GATEWAY_TOKEN=
# AES-256-GCM key encrypting the LLM provider keys stored in PostgreSQL.
# Changing it makes every stored key unreadable.
# Generate one with: openssl rand -hex 32
GOCLAW_ENCRYPTION_KEY=
-5
View File
@@ -93,8 +93,3 @@ user.
`ghcr.io/openclaw/openclaw:latest-browser` is the latest stable release with
Playwright Chromium built in, published by the project's release automation.
Upstream publishes no major tag.
On ARM64, release 2026.9.8 cannot find its bundled Chromium ("No supported
browser found"); the fix is merged upstream but not yet released. Everything
except browser automation works meanwhile, and the browser starts working on
the first pull after a release that contains the fix, with no change here.
+6 -12
View File
@@ -2,6 +2,10 @@
#
# cp .env.example .env
# Container hostname, shown as the host label in the web UI. Also passed in as
# HOST -- the name zsh's prompt shows.
SERVICE_HOSTNAME=paseo
# Password for the daemon API and web UI. Also the paseo user's login password,
# so it is what `sudo` asks for inside a terminal.
# Generate one with: openssl rand -base64 24
@@ -11,25 +15,15 @@ PASEO_PASSWORD=
# Coolify/Dokploy must be listed here. IPs and localhost are always allowed.
PASEO_HOSTNAMES=
# Proxy source IPs whose X-Forwarded-Proto the daemon trusts. Without this it
# trusts loopback only, reads the request as plain HTTP behind Coolify/Dokploy,
# and tells the web UI to open ws:// from an HTTPS page -- which browsers block.
# `uniquelocal` covers the private ranges Docker bridge networks use.
# Proxy source IPs whose X-Forwarded-Proto the daemon trusts.
PASEO_TRUSTED_PROXIES=uniquelocal
# Agent CLIs to install on start, if not already present. Space- or
# comma-separated, from: claude codex opencode copilot omp pi. Leave empty to
# install none. The first start with a new paseo-home volume downloads a few
# hundred MB per agent and takes a while; later starts only check.
# install none.
AGENTS=claude codex
# Git identity for agents and terminals, as author and committer. git reads
# these directly, so no `git config` step is needed.
GIT_NAME=
GIT_EMAIL=
# Container hostname, shown as the host label in the web UI. Without it the
# label is a random container ID. Also passed in as HOST -- the name zsh's
# prompt shows. Not named HOSTNAME: the deploying shell's own HOSTNAME would
# override it.
SERVICE_HOSTNAME=paseo
+1 -2
View File
@@ -36,8 +36,7 @@ for agent in ${agents//,/ }; do
continue
fi
# 126 and 127 are the shell's own codes for a binary that is missing or
# cannot be executed; any other code means it ran.
# Skip the agent when its command runs.
rc=0
/usr/sbin/gosu paseo bash -c '"$0" --version' "$agent" >/dev/null 2>&1 \
|| rc=$?
+6 -1
View File
@@ -1,9 +1,14 @@
# traffmonetizer
[TraffMonetizer](https://traffmonetizer.com) bandwidth-sharing client, defined
in `compose.yml` with `container_name: tm` and `restart: always`. It
in `compose.yml` with `restart: always`. It
only makes outbound connections, so there is no port to map a domain to.
`restart: always` instead of `unless-stopped` is on purpose: the client should
be restarted as often as possible. Docker brings it back even after a manual
stop once the daemon or host restarts. The Coolify app also has no watch path
for the same reason, so every push to the repository redeploys it.
The image tag is `arm64v8`. Change it to match the host architecture.
## Environment
-2
View File
@@ -1,8 +1,6 @@
version: '3.8'
services:
traffmonetizer:
image: 'traffmonetizer/cli_v2:arm64v8'
container_name: tm
restart: always
command: 'start accept --token ${TOKEN}'
environment:
+3 -3
View File
@@ -14,7 +14,7 @@ takes a few minutes longer before the desktop answers.
## Setup
1. Set `PASSWORD`.
1. Set `CUSTOM_USER` and `PASSWORD`.
2. Map the domain to port `3000` and deploy.
3. Open the domain and log in with `CUSTOM_USER` / `PASSWORD`.
@@ -25,11 +25,11 @@ The image's own HTTPS port `3001`, with a self-signed certificate, is unused.
| Variable | Default | Purpose |
| --- | --- | --- |
| `CUSTOM_USER` / `PASSWORD` | `miti99` / — | Login for the web desktop |
| `CUSTOM_USER` / `PASSWORD` | — | Login for the web desktop |
| `TZ` | `Asia/Ho_Chi_Minh` | Desktop timezone |
| `TITLE` | optional | Browser tab title |
`PASSWORD` is required: without it the image serves the desktop, with a
`CUSTOM_USER` and `PASSWORD` are required. Without `PASSWORD` the image serves the desktop, with a
shell and `sudo`, to anyone who opens the domain.
`PUID`/`PGID` are pinned to `1000` in `compose.yml`; the `Dockerfile` depends
+1 -1
View File
@@ -4,7 +4,7 @@ services:
restart: unless-stopped
shm_size: 1gb
environment:
- CUSTOM_USER=${CUSTOM_USER:-miti99}
- CUSTOM_USER=${CUSTOM_USER:?required}
- PASSWORD=${PASSWORD:?required}
- PUID=1000
- PGID=1000