> ## Documentation Index
> Fetch the complete documentation index at: https://artemiscity.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets and environment setup

> Generate and provision the .env files Artemis City reads at runtime — one per language layer — with a single script.

Artemis City is split across a Python core, a TypeScript Express API, and a memory-layer MCP server. Each layer reads its own `.env` file from a different location, and several keys (notably `MCP_API_KEY`) must match across files for cross-service authentication to work.

The `setup_secrets.sh` script in the repository root provisions every `.env` the codebase actually reads, generates fresh keys, and places each key in the file its consumer expects.

## When to use this

* You just cloned the repo and need to bring up a working local stack.
* You rotated keys and want all `.env` files reissued with matching values.
* You're wiring up the TypeScript Express API (`app/api`) for the first time and need its auth tuple set correctly.

If you only run the Python core and never touch the Express API or the memory-layer MCP server, you can still use this script — files for absent components are skipped silently.

## What it provisions

The script writes up to four `.env` files, each next to the consumer that reads it:

| Env file                                | Consumer                                                                                          |
| --------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `.env`                                  | Python core — orchestrator, memory bus, registry, and the FastAPI dashboard in `app/api/main.py`. |
| `app/api/.env`                          | TypeScript Express API (`app/api/index.ts`) and its auth middleware.                              |
| `src/.env`                              | Memory-layer Python.                                                                              |
| `src/Artemis Agentic Memory Layer/.env` | Memory-layer MCP server. Skipped silently if the directory is absent.                             |

## Generated keys

The script generates three secrets with `openssl rand -hex 32` (falling back to Python's `secrets.token_hex(32)` if `openssl` is unavailable):

| Key                       | Written to             | Purpose                                                                                                                                                   |
| ------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MCP_API_KEY`             | every file, same value | Shared MCP / cross-service authentication. The Python core, the TS Express API, and the memory MCP server all compare against this.                       |
| `FASTAPI_API_KEY`         | root `.env`            | Auth for the FastAPI dashboard at `app/api/main.py`. Clients send it as `X-API-Key`.                                                                      |
| `ARTEMIS_API_KEY_DEFAULT` | `app/api/.env`         | TS Express admin key. Written as the `key:role:perms` tuple that `app/api/middleware/auth.ts` parses — for example `<hex>:admin:read,write,delete,admin`. |

`MCP_API_KEY` is the only key that must match across files. The other two are scoped to a single layer.

## Running the script

From the repository root:

```bash theme={null}
./setup_secrets.sh
```

The script:

1. Generates `MCP_API_KEY`, `FASTAPI_API_KEY`, and `ARTEMIS_API_KEY_DEFAULT`.
2. For each target, copies the matching `.env.example`, substitutes placeholders with the generated values, and `chmod 600`s the result.
3. Verifies each written file is matched by `.gitignore` and warns if it is not.
4. Prints the generated keys at the end so you can copy them into a password manager.

Re-running is safe: each existing `.env` prompts before overwrite, defaulting to **No**. Missing example files are skipped without error.

## TypeScript API key format

The TS Express API supports multiple keys, one per logical caller. Each key is configured as an environment variable named `ARTEMIS_API_KEY_<NAME>`, with the value being a colon-separated tuple:

```
ARTEMIS_API_KEY_<NAME>=<key>:<role>:<perm1,perm2,...>
```

For example, the default admin key written by the script looks like:

```bash theme={null}
ARTEMIS_API_KEY_DEFAULT=4a8c…d91f:admin:read,write,delete,admin
```

To add a read-only service account, append another variable to `app/api/.env`:

```bash theme={null}
ARTEMIS_API_KEY_READONLY=<hex>:reader:read
```

If no `ARTEMIS_API_KEY_*` variable is set, the TS API falls back to `MCP_API_KEY` and assigns it the `admin` role.

## `app/api/.env` reference

The TypeScript API reads the following variables (see `app/api/.env.example` for the full template):

| Variable                 | Default                  | Purpose                                                                           |
| ------------------------ | ------------------------ | --------------------------------------------------------------------------------- |
| `API_PORT`               | `4000`                   | Express listen port.                                                              |
| `NODE_ENV`               | `development`            | `development` or `production`.                                                    |
| `SKIP_AUTH`              | unset                    | When `true` *and* `NODE_ENV=development`, bypasses auth. Never set in production. |
| `ARTEMIS_API_KEY_<NAME>` | —                        | One or more API keys as `key:role:perms` tuples.                                  |
| `MCP_API_KEY`            | —                        | Fallback admin key when no `ARTEMIS_API_KEY_*` is set.                            |
| `ARTEMIS_PYTHON`         | `python3`                | Interpreter used to invoke the Python bridge.                                     |
| `ARTEMIS_REPO_ROOT`      | auto-detected            | Override for the repo root the bridge resolves against.                           |
| `ARTEMIS_REGISTRY_DB`    | `data/agent_registry.db` | Registry SQLite path.                                                             |
| `OBSIDIAN_VAULT_PATH`    | `<repo>/obsidian_vault`  | Vault filesystem path used by the Python core via the bridge.                     |

## After the script runs

1. Add your Obsidian REST API key to the root `.env`:

   ```bash theme={null}
   OBSIDIAN_API_KEY=<key from Obsidian → Settings → Local REST API>
   ```

2. If your Obsidian vault is not at `<repo>/obsidian_vault`, set `OBSIDIAN_VAULT_PATH` in the root `.env`.

3. The `ARTEMIS_API_KEY_DEFAULT` and `MCP_API_KEY` values in `app/api/.env` already match the Python core — no extra wiring needed.

## Security notes

* Every file written by the script is `chmod 600` — readable and writable only by the owner.
* `.gitignore` covers `.env` at any depth. The script runs `git check-ignore` per file and warns if any are not ignored.
* The script never overwrites a file without prompting. Re-running it on a working checkout will not silently rotate keys.
* Production secrets belong in per-environment GitHub Environment secrets (see [Environments](/Documentation/operations/environments)) — not in committed `.env` files or repo-wide secrets.


## Related topics

- [Environments](/Documentation/operations/environments.md)
- [Changelog](/Changelog/changelog.md)
- [Project structure](/Documentation/operations/project-structure.md)
- [Agentic Memory Layer (MCP server)](/Documentation/integrations/agentic-memory-layer.md)
- [API Reference](/api/api-reference.md)
