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
53 changes: 49 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,73 @@ An example systemd service to run fmsgd as a service on startup

ASSUMES:
* Directory `/opt/fmsgd` has been created and contains built executable: `fmsgd`
* Text file `/opt/fmsgd/env` exists containing environment variables
* Text file `/opt/fmsgd/env` exists containing environment variables (example below)
* User `fmsg` has been created and has
- read and execute permissions to `/opt/fmsgd/`, e.g. with `chown -R fmsg:fmsg /opt/fmsgd` after `mkdir /opt/fmsgd`
- write permissions to FMSG_DATA_DIR
* Directory `/var/lib/fmsgd` has been created and owned by fmsg

`/etc/systemd/system/fmsgd.service`

```
[Unit]
Description=fmsg Host
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
EnvironmentFile=/opt/fmsgd/env
ExecStart=/opt/fmsgd/fmsgd "0.0.0.0"
Type=simple

User=fmsg
Group=fmsg

EnvironmentFile=/opt/fmsgd/env

ExecStart=/opt/fmsgd/fmsgd 0.0.0.0
WorkingDirectory=/opt/fmsgd

Restart=on-failure
RestartSec=3

# --- Filesystem access ---
ReadWritePaths=/opt/fmsgd
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReadWritePaths=/opt/fmsgd grants write access to the installation directory. The daemon code appears to write only under FMSG_DATA_DIR (e.g., filepath.Join(DataDir, ...) in src/host.go), so this is broader than necessary. For least privilege, consider removing write access to /opt/fmsgd (keep it read-only) and only allow writes to /var/lib/fmsgd (or whatever FMSG_DATA_DIR is set to).

Suggested change
ReadWritePaths=/opt/fmsgd

Copilot uses AI. Check for mistakes.
ReadWritePaths=/var/lib/fmsgd
PrivateTmp=true

# --- Hardening ---
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

# --- Logging ---
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
```

```
FMSG_DATA_DIR=/var/lib/fmsgd/
FMSG_DOMAIN=example.com
FMSG_ID_URL=http://127.0.0.1:8080


FMSG_MAX_MSG_SIZE=10240
FMSG_MAX_PAST_TIME_DELTA=604800
FMSG_MAX_FUTURE_TIME_DELTA=300
FMSG_MIN_DOWNLOAD_RATE=5000
FMSG_MIN_UPLOAD_RATE=5000
FMSG_READ_BUFFER_SIZE=1600

PGHOST=127.0.0.1
PGPORT=5432
PGUSER=
PGPASSWORD=
PGDATABASE=fmsgd
```

```
Comment on lines +113 to 133
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The environment-variable example is now duplicated here and in src/.env.example, and they already diverge (e.g., .env.example includes PGSSLMODE but this README block does not). To avoid future drift, consider referencing/including the .env.example file from the README (or ensure both lists stay identical, including the Postgres variables you expect users to set).

Suggested change
```
FMSG_DATA_DIR=/var/lib/fmsgd/
FMSG_DOMAIN=example.com
FMSG_ID_URL=http://127.0.0.1:8080
FMSG_MAX_MSG_SIZE=10240
FMSG_MAX_PAST_TIME_DELTA=604800
FMSG_MAX_FUTURE_TIME_DELTA=300
FMSG_MIN_DOWNLOAD_RATE=5000
FMSG_MIN_UPLOAD_RATE=5000
FMSG_READ_BUFFER_SIZE=1600
PGHOST=127.0.0.1
PGPORT=5432
PGUSER=
PGPASSWORD=
PGDATABASE=fmsgd
```
```
See `src/.env.example` for the canonical environment-variable example and the full, current set of `FMSG_*` and PostgreSQL `PG*` variables to configure.

Copilot uses AI. Check for mistakes.
sudo systemctl daemon-reload
sudo systemctl enable fmsgd
Expand Down
22 changes: 22 additions & 0 deletions src/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# fmsgd Environment Variables

# Required
FMSG_DATA_DIR=/var/lib/fmsgd/
FMSG_DOMAIN=example.com
FMSG_ID_URL=http://127.0.0.1:8080


FMSG_MAX_MSG_SIZE=10240
FMSG_MAX_PAST_TIME_DELTA=604800
FMSG_MAX_FUTURE_TIME_DELTA=300
FMSG_MIN_DOWNLOAD_RATE=5000
FMSG_MIN_UPLOAD_RATE=5000
FMSG_READ_BUFFER_SIZE=1600

# PostgreSQL connection variables (see https://www.postgresql.org/docs/current/libpq-envars.html)
PGHOST=127.0.0.1
PGPORT=5432
PGUSER=
PGPASSWORD=
PGDATABASE=fmsgd
PGSSLMODE=disable
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PGSSLMODE=disable is an insecure default for many deployments (it disables TLS to Postgres). Consider omitting it from the example or setting a safer default (e.g., require/verify-full) and adding a short comment indicating when disable is appropriate (local socket / trusted localhost only).

Suggested change
PGSSLMODE=disable
# Use disable only for local socket or trusted localhost development.
PGSSLMODE=require

Copilot uses AI. Check for mistakes.
2 changes: 1 addition & 1 deletion src/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func setDomain() {
if !hasValue {
log.Panicln("ERROR: FMSG_DOMAIN not set")
}
_, err := net.LookupHost(domain)
_, err := net.LookupHost("fmsg." + domain)
if err != nil {
log.Panicf("ERROR: FMSG_DOMAIN, %s: %s\n", domain, err)
}
Expand Down
Loading