Added doker compose
All checks were successful
Publish Metadata Agent Image / build-and-push-image (push) Successful in 1m6s
Publish Web Player Image / build-and-push-image (push) Successful in 1m9s
Publish Server Image / build-and-push-image (push) Successful in 2m16s

This commit is contained in:
2026-03-18 13:04:13 +00:00
parent a50efd0082
commit f4fa01ef7e
6 changed files with 130 additions and 2 deletions

3
.env_example Normal file
View File

@@ -0,0 +1,3 @@
OLLAMA_URL=https://ollama.host.com
OLLAMA_AUTH="Basic <BASE64 Auth string>"
#OLLAMA_AUTH="Bearer <TOKEN>"

3
.gitignore vendored
View File

@@ -1 +1,4 @@
/target
/inbox
/storage
.env

View File

@@ -164,7 +164,59 @@ All options can be set via CLI flags or environment variables.
| `--oidc-client-secret` | `FURUMI_PLAYER_OIDC_CLIENT_SECRET` | — | OIDC client secret |
| `--oidc-redirect-url` | `FURUMI_PLAYER_OIDC_REDIRECT_URL` | — | OIDC redirect URL |
| `--oidc-session-secret` | `FURUMI_PLAYER_OIDC_SESSION_SECRET` | *(random)* | Session HMAC secret |
## Docker Compose
The easiest way to run the entire backend stack (PostgreSQL, Agent, Web Player, and gRPC Server) is using Docker Compose.
### Quick Start
1. **Prepare directories**:
```bash
mkdir -p inbox storage
```
2. **Start the services**:
```bash
docker compose up -d
```
3. **Check logs**:
```bash
docker compose logs -f
```
The following services will be available:
- **Web Player**: [http://localhost:8085](http://localhost:8085)
- **Agent Admin UI**: [http://localhost:8090](http://localhost:8090)
- **Metrics**: [http://localhost:9090/metrics](http://localhost:9090/metrics)
> [!NOTE]
> The Agent expects Ollama to be running. By default, it tries to connect to the host at `http://localhost:11434`.
### Reference Commands
- **Start**: `docker compose up -d`
- **Stop**: `docker compose stop`
- **Stop and remove containers**: `docker compose down`
- **Clear database and storage**: `docker compose down -v`
### Environment Variables
To configure the Agent (especially for remote Ollama or private models) and database, create an `.env` file in the root directory:
```env
# Database
POSTGRES_PASSWORD=secure-password
# LLM (Ollama)
OLLAMA_URL=http://your-ollama-host:11434
OLLAMA_AUTH="Bearer your-token"
# Server Security
FURUMI_TOKEN=secure-server-token
```
For more options, refer to the [Configuration](#configuration) section.
## Docker
Pre-built images are available on Docker Hub:

60
docker-compose.yml Normal file
View File

@@ -0,0 +1,60 @@
services:
db:
image: postgres:17-alpine
container_name: furumi-db
environment:
POSTGRES_DB: ${POSTGRES_DB:-furumi}
POSTGRES_USER: ${POSTGRES_USER:-furumi}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-furumi}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U furumi -d furumi"]
interval: 5s
timeout: 5s
retries: 5
agent:
build:
context: .
dockerfile: Dockerfile.agent
container_name: furumi-agent
depends_on:
db:
condition: service_healthy
ports:
- "8090:8090"
environment:
FURUMI_AGENT_DATABASE_URL: "postgres://${POSTGRES_USER:-furumi}:${POSTGRES_PASSWORD:-furumi}@db:5432/${POSTGRES_DB:-furumi}"
FURUMI_AGENT_INBOX_DIR: "/inbox"
FURUMI_AGENT_STORAGE_DIR: "/storage"
FURUMI_AGENT_OLLAMA_URL: "${OLLAMA_URL:-http://host.docker.internal:11434}"
FURUMI_AGENT_OLLAMA_AUTH: "${OLLAMA_AUTH:-CHANGE-ME}"
FURUMI_PLAYER_BIND: "0.0.0.0:8090"
volumes:
- ./inbox:/inbox
- ./storage:/storage
extra_hosts:
- "host.docker.internal:host-gateway"
restart: always
web-player:
build:
context: .
dockerfile: Dockerfile.web-player
container_name: furumi-web-player
depends_on:
db:
condition: service_healthy
ports:
- "8085:8085"
environment:
FURUMI_PLAYER_DATABASE_URL: "postgres://${POSTGRES_USER:-furumi}:${POSTGRES_PASSWORD:-furumi}@db:5432/${POSTGRES_DB:-furumi}"
FURUMI_PLAYER_STORAGE_DIR: "/storage"
FURUMI_PLAYER_BIND: "0.0.0.0:8085"
volumes:
- ./storage:/storage
restart: always
volumes:
pgdata:

View File

@@ -32,6 +32,10 @@ pub struct Args {
#[arg(long, env = "FURUMI_AGENT_OLLAMA_MODEL", default_value = "qwen3:14b")]
pub ollama_model: String,
/// Authorization header value for Ollama API (e.g. "Bearer <token>" or "Basic <base64>")
#[arg(long, env = "FURUMI_AGENT_OLLAMA_AUTH")]
pub ollama_auth: Option<String>,
/// Inbox scan interval in seconds
#[arg(long, env = "FURUMI_AGENT_POLL_INTERVAL_SECS", default_value_t = 30)]
pub poll_interval_secs: u64,

View File

@@ -22,6 +22,7 @@ pub async fn normalize(
&state.config.ollama_model,
&state.system_prompt,
&user_message,
state.config.ollama_auth.as_deref(),
)
.await?;
@@ -125,6 +126,7 @@ async fn call_ollama(
model: &str,
system_prompt: &str,
user_message: &str,
auth: Option<&str>,
) -> anyhow::Result<String> {
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(120))
@@ -151,7 +153,11 @@ async fn call_ollama(
tracing::info!(%url, model, prompt_len = user_message.len(), "Calling Ollama API...");
let start = std::time::Instant::now();
let resp = client.post(&url).json(&request).send().await?;
let mut req = client.post(&url).json(&request);
if let Some(auth_header) = auth {
req = req.header("Authorization", auth_header);
}
let resp = req.send().await?;
let elapsed = start.elapsed();
if !resp.status().is_success() {