Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# The Docker build context is the repository root (docker/compose.yml sets
# `context: ..`) and both Dockerfiles pull it into the builder stage with
# `COPY . .`. `make docker-build` stages the LND cert and admin macaroon in
# docker/config/lnd/ right before `docker compose build`, so without this entry
# a spend-capable credential would be shipped into the build context and left
# in the builder layer and its cache. .gitignore already keeps it out of git,
# but Docker does not read .gitignore.
docker/config/
docker/.env
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@
- Add a language specifier to every fenced code block. Static analysis (markdownlint MD040) flags blocks without a language identifier. Example: ` ```flutter test ` instead of bare ` ``` `.

## Security & Configuration Tips
- Do not commit populated `settings.toml`. Copy from `settings.tpl.toml` to `~/.mostro/settings.toml` for local runs.
- Protect LND credentials before `make docker-build`.
- Do not commit populated `settings.toml`. Install it from `settings.tpl.toml` with `install -d -m 700 ~/.mostro && install -m 600 settings.tpl.toml ~/.mostro/settings.toml` for local runs: the file carries `nsec_privkey` and the directory also holds `mostro.db`.
- Protect LND credentials before `make docker-build`. The admin macaroon is spend-capable: copy it with `install -m 600` (never plain `cp`, which inherits the source or destination mode) and keep its directory at `0700`.
- Scrub logs that might leak invoices or Nostr keys; rotate secrets promptly if exposed.
26 changes: 23 additions & 3 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,11 @@ adduser --disabled-login mostro # keep pressing enter until it ends
cd /opt/mostro
```

Create a new settings file from `/opt/mostro/mostro/settings.tpl.toml` and save it to `/opt/mostro`:
Create a new settings file from `/opt/mostro/mostro/settings.tpl.toml` and save it to `/opt/mostro`. `/opt/mostro` holds `settings.toml`, whose `nsec_privkey` is the daemon's identity, and the `mostro.db` created later, so both the directory and the file are restricted to the service account — `install -m` rather than `cp`, which keeps whatever mode the template happens to have:

```bash
cp /opt/mostro/mostro/settings.tpl.toml /opt/mostro/settings.toml
install -d -m 700 -o mostro -g mostro /opt/mostro
install -m 600 -o mostro -g mostro /opt/mostro/mostro/settings.tpl.toml /opt/mostro/settings.toml
```

Update the file `/opt/mostro/settings.toml` with your favourite editor.
Expand All @@ -108,6 +109,25 @@ Here some parameters you might want to change:
- **nsec_privkey** : Your mostro private key
- **relays** : List of relays you want to connect to

### Protect the admin macaroon

The admin macaroon is a spend-capable credential: any user who can read it has full control of the LND node, including the funds escrowed in Mostro's hold invoices. Access should reach no further than the `mostro` service account created above and the LND account the node already runs as.

If LND runs on this same VPS, grant access through the node's group instead of loosening the file (LND creates `admin.macaroon` with mode `0640`):

```bash
usermod -aG lnd mostro
```

If you copy the macaroon into `/opt/mostro` instead, install it owner-readable only and hand it to the service account — do not use plain `cp`, which keeps whatever mode the source file or an existing destination happens to have:

```bash
install -d -m 700 -o mostro -g mostro /opt/mostro/lnd
install -m 600 -o mostro -g mostro /path/to/lnd/admin.macaroon /opt/mostro/lnd/admin.macaroon
```

Then point `lnd_macaroon_file` at `/opt/mostro/lnd/admin.macaroon`.

## Database

The data is saved in a sqlite db file named by default `mostro.db`, this file is saved on the root directory of the project and can be change just editing the `url` var on the `[database]` section in `settings.toml` file.
Expand All @@ -125,7 +145,7 @@ Check the DB files are there

```bash
ls -al /opt/mostro
drwxrwxr-x root root 4.0 KB Fri Jun 14 15:52:07 2024 .
drwx------ mostro mostro 4.0 KB Fri Jun 14 15:52:07 2024 .
Comment thread
AndreaDiazCorreia marked this conversation as resolved.
drwxr-x--- root root 4.0 KB Sat Jun 15 15:50:32 2024 ..
.rw-r--r-- root root 52 KB Fri May 31 16:35:34 2024 mostro.db
.rw-r--r-- root root 32 KB Sat Jun 15 15:28:23 2024 mostro.db-shm
Expand Down
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ VERSION := $(shell grep "^version = " Cargo.toml | sed "s/version = \"\(.*\)\"/\
docker-build:
@set -o pipefail; \
cd docker && \
mkdir -p config/lnd && \
install -d -m 700 config config/lnd && \
Comment thread
AndreaDiazCorreia marked this conversation as resolved.
Outdated
echo "Checking LND files..." && \
echo "LND_CERT_FILE=$${LND_CERT_FILE}" && \
echo "LND_MACAROON_FILE=$${LND_MACAROON_FILE}" && \
Expand All @@ -27,15 +27,20 @@ docker-build:
exit 1; \
fi && \
echo "Copying LND cert and macaroon to docker config" && \
cp -v $${LND_CERT_FILE} config/lnd/tls.cert && \
cp -v $${LND_MACAROON_FILE} config/lnd/admin.macaroon && \
install -m 644 "$${LND_CERT_FILE}" config/lnd/tls.cert && \
install -m 600 "$${LND_MACAROON_FILE}" config/lnd/admin.macaroon && \
Comment thread
AndreaDiazCorreia marked this conversation as resolved.
Comment thread
AndreaDiazCorreia marked this conversation as resolved.
echo "Wrote config/lnd/tls.cert (mode 644) and config/lnd/admin.macaroon (mode 600)" && \
echo "config and config/lnd are mode 700: settings.toml holds nsec_privkey and mostro.db lands there too" && \
echo "Note: the container runs as uid/gid 1000 by default. If your user is not uid 1000," && \
echo ' export MOSTRO_CONTAINER_USER=$$(id -u):$$(id -g) before make docker-up' && \
echo "Building docker image" && \
docker compose build

docker-up:
@set -o pipefail; \
cd docker && \
echo "Copying Nostr relay config" && \
install -d -m 700 config && \
mkdir -p config/relay && \
cp -v ./relay_config.toml config/relay/config.toml && \
echo "Starting services" && \
Expand All @@ -45,6 +50,7 @@ docker-relay-up:
@set -o pipefail; \
cd docker && \
echo "Copying Nostr relay config" && \
install -d -m 700 config && \
mkdir -p config/relay && \
cp -v ./relay_config.toml config/relay/config.toml && \
echo "Starting Nostr relay" && \
Expand Down
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,10 @@ cargo build --release
# Install to system
sudo install target/release/mostrod /usr/local/bin

# Setup configuration
mkdir -p ~/.mostro
cp settings.tpl.toml ~/.mostro/settings.toml
# Setup configuration (0700/0600: settings.toml holds nsec_privkey, and
# mostro.db lands in the same directory)
install -d -m 700 ~/.mostro
install -m 600 settings.tpl.toml ~/.mostro/settings.toml
# Edit ~/.mostro/settings.toml (see Configuration section)

# Initialize database (optional — mostrod also migrates on first connect)
Expand Down Expand Up @@ -479,9 +480,10 @@ Best for: Local testing, development environments, quick experiments
git clone https://github.com/MostroP2P/mostro.git
cd mostro

# Setup configuration
mkdir -p docker/config
cp settings.tpl.toml docker/config/settings.toml
# Setup configuration (0700/0600: the config dir ends up holding nsec_privkey,
# the LND credentials and mostro.db)
install -d -m 700 docker/config
install -m 600 settings.tpl.toml docker/config/settings.toml
# Edit docker/config/settings.toml

# Build and run (provide LND paths as environment variables)
Expand All @@ -495,6 +497,8 @@ This starts:
- Mostro daemon (exposed via configured relays)
- Local Nostr relay (port 7000 by default)

`make docker-build` installs the LND admin macaroon into `docker/config/lnd/` with mode `0600`, since it grants full control of your node, and sets `docker/config` and `docker/config/lnd` to mode `0700` — the same directory holds `settings.toml` and `mostro.db`. The container runs as uid/gid 1000 by default; if your user is not uid 1000, `export MOSTRO_CONTAINER_USER=$(id -u):$(id -g)` so it runs as you and can read those files.

**Stop**: `make docker-down`

For detailed Docker setup, see [docker/README.md](docker/README.md).
Expand Down Expand Up @@ -565,6 +569,8 @@ payment_retries_interval = 60 # seconds between retries

**Required**: LND connection details. Mostro needs admin macaroon for hold invoice management.

**Permissions**: the admin macaroon is a spend-capable credential — anyone who can read it controls the node, including the funds escrowed in Mostro's hold invoices. Keep it readable only by the account running `mostrod`, or by that account and LND's group (`chmod 600` for a private copy, `chmod o=` to keep group access). mostrod logs a warning at startup when the file's `other` permission bits are set.

---

#### Nostr Configuration
Expand All @@ -590,6 +596,8 @@ rana --vanity mostro

**Important**: Never reuse keys between Mostro instances. Each daemon needs a unique identity.

**Permissions**: `settings.toml` holds `nsec_privkey` in plaintext unless you move it to the environment (see below), and `mostro.db` sits in the same directory. Keep both owner-only: `chmod 700` on the settings directory and `chmod 600` on `settings.toml`. mostrod already creates them that way when it has to — both through the interactive setup wizard and through the template copy it makes on a non-interactive first run — but a directory or file you create yourself with `mkdir`, `cp` or `curl` inherits your umask instead, so use `install -d -m 700` and `install -m 600`.

##### Providing the nsec via environment variable

For better separation of secrets from config, Mostro can read the nsec from the
Expand Down
8 changes: 7 additions & 1 deletion docker/ENV_VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ This document describes the environment variables used by the Docker setup.
- `LND_MACAROON_FILE`: Path to the LND admin macaroon file on your host system
- Example: `~/.polar/networks/1/volumes/lnd/alice/data/chain/bitcoin/regtest/admin.macaroon`

These files are copied to `docker/config/lnd/` during the build process.
These files are copied to `docker/config/lnd/` during the build process: the cert with mode `0644`, the admin macaroon with mode `0600`, both inside a directory with mode `0700`. The macaroon grants full control of your LND node, so it is never left readable by other users on the host. The `docker/config` root is set to mode `0700` as well, since `settings.toml` (which carries `nsec_privkey`) and `mostro.db` live beside the credentials.

The copies belong to the user that ran the command, and the container runs as uid/gid 1000 by default. If your user is not uid 1000, run the container as yourself with the optional variable below rather than handing the config directory over to uid 1000.

## Optional Variables

- `MOSTRO_RELAY_LOCAL_PORT`: Port number for the local Nostr relay (defaults to 7000)
- Used in `compose.yml` for port mapping
- Example: `export MOSTRO_RELAY_LOCAL_PORT=7000`

- `MOSTRO_CONTAINER_USER`: uid/gid the `mostro` container runs as (defaults to `1000:1000`, the image's `mostrouser`)
- Set it when your host user is not uid 1000, so the container can read the `0600` macaroon and write `mostro.db` in the mounted config directory
- Example: `export MOSTRO_CONTAINER_USER=$(id -u):$(id -g)`

- `MOSTRO_DB_PASSWORD`: Not used (database encryption was removed). Kept in `compose.yml` for backward compatibility; can be omitted or left empty.

## Usage Examples
Expand Down
50 changes: 38 additions & 12 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ To build and run the Docker container using Docker Compose, follow these steps:

```sh
cd docker
mkdir -p config
cp ../settings.tpl.toml config/settings.toml
install -d -m 700 config
install -m 600 ../settings.tpl.toml config/settings.toml
```

Mode `0700` on `config` and `0600` on `settings.toml` because that directory ends up holding every secret this deployment has: `nsec_privkey` in `settings.toml`, the LND credentials in `config/lnd/`, and the `mostro.db` the daemon writes. `install -d -m 700` also tightens a `config` directory an earlier `mkdir -p` left at `0755`.

_Don't forget to edit `lnd_grpc_host`, `nsec_privkey` and `relays` fields in the `config/settings.toml` file. Note that paths in `settings.toml` refer to paths **inside the container**, so use `/config/lnd/tls.cert` and `/config/lnd/admin.macaroon` for the LND certificate and macaroon files (these will be copied there by `make docker-build`)._

3. Build the docker image. You need to provide the `LND_CERT_FILE` and `LND_MACAROON_FILE` environment variables with the paths to your LND TLS certificate and macaroon files. These files will be copied to the `docker/config/lnd` directory by the `make docker-build` command. The build process will validate that these variables are set and that the files exist before proceeding.
Expand All @@ -62,6 +64,16 @@ To build and run the Docker container using Docker Compose, follow these steps:
make docker-build
```

The admin macaroon grants full control of your LND node, so `make docker-build` writes it to `config/lnd/admin.macaroon` with mode `0600` (owner only) inside a `config/lnd` directory with mode `0700`. The `config` root itself is set to `0700` as well, since `settings.toml` and `mostro.db` sit next to the credentials. All of them belong to the user that ran the command.

The container runs as uid/gid 1000 by default, which matches the first user account on most hosts. If yours is not uid 1000, run the container as yourself instead of handing the config directory over — the daemon also writes `mostro.db` into it:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

```sh
export MOSTRO_CONTAINER_USER=$(id -u):$(id -g)
```

`compose.yml` reads that variable, so export it in the same shell you run `make docker-up` from.

4. [Optional] Set the `MOSTRO_RELAY_LOCAL_PORT` environment variable to the port you want to use for the local relay (defaults to 7000 if not set). This can be set before running `make docker-up`:

```sh
Expand Down Expand Up @@ -89,19 +101,24 @@ You can run the plain Mostro image without building locally. Use a single **conf
**Option A — download the template** (from the [settings.tpl.toml](https://github.com/MostroP2P/mostro/blob/main/settings.tpl.toml) repo file):

```sh
mkdir -p ~/mostro-config/lnd
install -d -m 700 ~/mostro-config ~/mostro-config/lnd
curl -sL https://raw.githubusercontent.com/MostroP2P/mostro/main/settings.tpl.toml -o ~/mostro-config/settings.toml
chmod 600 ~/mostro-config/settings.toml
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
```

**Option B — use the entrypoint default:** run the container once with an empty config dir; the entrypoint copies a default `settings.toml` (from the image, built from `settings.tpl.toml`) into `/config`. Stop the container, edit the file on the host (e.g. `~/mostro-config/settings.toml`), then start the container again.
The config root is `0700` and `settings.toml` is `0600` because both `nsec_privkey` and, later, `mostro.db` live there. `curl` creates the file under your umask, typically `0644`, so the mode has to be set afterwards.

**Option B — use the entrypoint default:** create the config dir with `install -d -m 700 ~/mostro-config ~/mostro-config/lnd`, then run the container once against it; the entrypoint installs a default `settings.toml` (from the image, built from `settings.tpl.toml`) into `/config` with mode `0600`. Stop the container, edit the file on the host (e.g. `~/mostro-config/settings.toml`), then start the container again.

2. Copy your LND TLS cert and macaroon into the config dir (so they appear at `/config/lnd/` in the container):
2. Copy your LND TLS cert and macaroon into the config dir (so they appear at `/config/lnd/` in the container). Use `install` rather than `cp`: `cp` keeps whatever mode the source file (or an already existing destination file) happens to have, while `install -m` sets the mode explicitly. The admin macaroon grants full control of your LND node, so it must not be readable by other users on the host:

```sh
cp /path/to/your/tls.cert ~/mostro-config/lnd/tls.cert
cp /path/to/your/admin.macaroon ~/mostro-config/lnd/admin.macaroon
install -m 644 /path/to/your/tls.cert ~/mostro-config/lnd/tls.cert
install -m 600 /path/to/your/admin.macaroon ~/mostro-config/lnd/admin.macaroon
```

Mode `0600` on the macaroon inside a `0700` directory means only their owner can reach the file, and the container runs as uid/gid 1000 by default. If your user is not uid 1000, run the container as yourself by adding `--user $(id -u):$(id -g)` to the `docker run` command in step 4 — that also lets it write `mostro.db` into your config directory.

3. Edit `~/mostro-config/settings.toml`: set `nsec_privkey`, `relays`, and for Docker set `lnd_cert_file` / `lnd_macaroon_file` to `/config/lnd/...`, `lnd_grpc_host` (e.g. `https://host.docker.internal:10009`), and `[database]` `url = "sqlite:///config/mostro.db"`.

4. Run the container. On Linux, add `--add-host=host.docker.internal:host-gateway` so the container can reach LND on the host:
Expand All @@ -126,25 +143,34 @@ Steps to run the plain Mostro image on a VPS (no repo clone; image from Docker H
2. **Create a config directory** (e.g. `/opt/mostro` or `~/mostro-config`):

```sh
mkdir -p /opt/mostro/lnd
install -d -m 700 -o 1000 -g 1000 /opt/mostro
install -d -m 700 -o 1000 -g 1000 /opt/mostro/lnd
Comment thread
AndreaDiazCorreia marked this conversation as resolved.
```

These steps run as root, while the container runs as uid/gid 1000, so both directories are handed to the container's user: it needs to write `mostro.db` into the config directory. Both are owner-only because of what goes in them — `nsec_privkey` in `settings.toml` and the database in the config root, the LND credentials in `lnd` (step 4).

3. **Get the settings template** into that directory as `settings.toml`:

- Either run the container once with an empty config dir; the entrypoint will copy the default template to `/config/settings.toml`. Stop the container, then edit the file on the host.
- Either run the container once with an empty config dir; the entrypoint installs the default template at `/config/settings.toml` with mode `0600`. Stop the container, then edit the file on the host.
- Or download the template and copy it:

```sh
curl -sL https://raw.githubusercontent.com/MostroP2P/mostro/main/settings.tpl.toml -o /opt/mostro/settings.toml
chmod 600 /opt/mostro/settings.toml
chown 1000:1000 /opt/mostro/settings.toml
```

4. **Put LND files** in the config dir so they appear at `/config/lnd/` in the container:
`curl` writes the file under root's umask, typically `0644` and root-owned, so the mode and the owner have to be set afterwards: the file receives `nsec_privkey` in step 5, and the container reads it as uid/gid 1000.

4. **Put LND files** in the config dir so they appear at `/config/lnd/` in the container. Use `install -m` rather than `cp`, which would keep whatever mode the source file (or an already existing destination file) happens to have:

```sh
cp /path/to/lnd/tls.cert /opt/mostro/lnd/tls.cert
cp /path/to/lnd/admin.macaroon /opt/mostro/lnd/admin.macaroon
install -m 644 /path/to/lnd/tls.cert /opt/mostro/lnd/tls.cert
install -m 600 -o 1000 -g 1000 /path/to/lnd/admin.macaroon /opt/mostro/lnd/admin.macaroon
```

The admin macaroon grants full control of your LND node — anyone who reads it can move the funds escrowed in Mostro's hold invoices — so it is installed owner-readable only, and `-o 1000 -g 1000` hands it to the container's user (as the `0700` directory from step 2 already was). Without that ownership, mode `0600` would leave mostrod unable to read the macaroon. (`-o`/`-g` require root; as a non-root user, drop them and run the steps as the account that owns the config dir.)
Comment thread
AndreaDiazCorreia marked this conversation as resolved.
Outdated

(If LND is on another host, you only need the cert and macaroon copied here; point `lnd_grpc_host` at that host in step 5.)

5. **Edit `/opt/mostro/settings.toml`**:
Expand Down
6 changes: 6 additions & 0 deletions docker/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ services:
dockerfile: docker/Dockerfile
volumes:
- ./config:/config # settings.toml and mostro.db
# The image's mostrouser is uid/gid 1000, so the default keeps the previous
# behaviour. Hosts whose user is not uid 1000 export
# MOSTRO_CONTAINER_USER=$(id -u):$(id -g) instead of handing ./config over
# to uid 1000 — the LND macaroon is installed 0600, and the daemon also
# needs to write mostro.db in the same directory.
user: "${MOSTRO_CONTAINER_USER:-1000:1000}"
platform: linux/amd64
networks:
- default
Expand Down
Loading