mirror of
https://github.com/tiennm99/composes.git
synced 2026-10-19 02:14:09 +00:00
Compare commits
12
Commits
ee2f92de19
...
f38a3a2871
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f38a3a2871 | ||
|
|
d889338306 | ||
|
|
feb6f035c8 | ||
|
|
fc85962f45 | ||
|
|
56111e9219 | ||
|
|
422eab8499 | ||
|
|
042d6bd6c0 | ||
|
|
4c5c6ed17e | ||
|
|
e4c74ef5cd | ||
|
|
0637a02051 | ||
|
|
272db135b7 | ||
|
|
98b0924ca7 |
No files matched your search
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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,9 +1,6 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
db:
|
||||
couchbase:
|
||||
image: couchbase
|
||||
container_name: db
|
||||
ports:
|
||||
- "8091-8097:8091-8097"
|
||||
- "9123:9123"
|
||||
|
||||
+1
-1
@@ -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
@@ -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"}`.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
gitea-mirror/
|
||||
.env
|
||||
purge.py
|
||||
@@ -1,3 +0,0 @@
|
||||
gitea/
|
||||
.env
|
||||
purge.py
|
||||
+1
-3
@@ -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=
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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=$?
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user