server-ovh-prod-01-main/docs/invoiceninja.md

198 lines
5.9 KiB
Markdown
Raw Normal View History

# Invoice Ninja
**Type**: Invoicing & Billing Application
**Domain**: https://invoice.hyperthrive.io
**Version**: 5.12.28
**Architecture**: Official Docker stack from [invoiceninja/dockerfiles](https://github.com/invoiceninja/dockerfiles)
**Deployment Date**: 2025-10-14
## Architecture
Invoice Ninja runs using the official Docker Compose stack with three services:
1. **invoiceninja-server-1** - Nginx web server (port 80 internal)
2. **invoiceninja-app-1** - Laravel application with supervisord (PHP-FPM, queue workers, scheduler)
3. **invoiceninja-db-1** - MariaDB 10.11 database
### Traefik Integration
The nginx service connects to the external `traefik` network and uses labels for automatic SSL/routing:
- **Domain**: invoice.hyperthrive.io
- **Protocol**: HTTPS via Let's Encrypt
- **Entry Point**: websecure (443)
- **Internal Port**: 80 (nginx)
### Directory Structure (Server)
```
~/services/invoiceninja/
├── docker-compose.yml # Main compose file
├── env # Environment configuration
├── config/
│ └── nginx/
│ └── in-vhost.conf # Nginx vhost config
├── docker/
│ ├── app/
│ │ ├── public/ # Application public files (shared with nginx)
│ │ └── storage/ # Application storage (logs, cache, uploads)
│ └── mysql/
│ └── data/ # Database files
```
**Important**: The `docker/app/` directories must be owned by user `1500:1500` (the container's runtime user).
## Common Operations
### Check Status
```bash
ssh jared@15.204.247.153 "docker ps --filter name=invoiceninja"
```
### View Logs
```bash
# Application logs
ssh jared@15.204.247.153 "docker logs invoiceninja-app-1 --tail 50"
# Database logs
ssh jared@15.204.247.153 "docker logs invoiceninja-db-1 --tail 50"
# Nginx logs
ssh jared@15.204.247.153 "docker logs invoiceninja-server-1 --tail 50"
```
### Update Invoice Ninja
```bash
ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
docker compose pull && \
docker compose up -d && \
docker exec invoiceninja-app-1 php artisan migrate --force && \
docker exec invoiceninja-app-1 php artisan optimize"
```
### Backup Database
```bash
ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
docker compose exec -T db sh -c 'exec mysqldump --all-databases -uroot -p\"\$MYSQL_ROOT_PASSWORD\"' \
> ~/backups/invoiceninja-$(date +%Y%m%d-%H%M%S).sql"
```
### Restore Database
```bash
ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
docker compose exec -T db sh -c 'exec mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\"' \
< ~/backups/invoiceninja-TIMESTAMP.sql"
```
### Restart Services
```bash
ssh jared@15.204.247.153 "cd ~/services/invoiceninja && docker compose restart"
```
### Run Artisan Commands
```bash
# Generic pattern
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan <command>"
# Examples
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan queue:work"
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan cache:clear"
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan db:seed"
```
## Key Configuration
### Environment Variables (env file)
Critical settings in `~/services/invoiceninja/env`:
- `APP_URL=https://invoice.hyperthrive.io` - Public URL
- `APP_KEY=base64:...` - Encryption key (DO NOT change after initial setup)
- `DB_HOST=db` - Database hostname (container name)
- `MYSQL_ROOT_PASSWORD` - DB root password
- `MYSQL_DATABASE=ninja` - Database name
- `MYSQL_USER=ninja` - DB user
- `MYSQL_PASSWORD` - DB password
- `TRUSTED_PROXIES=*` - Trust Traefik proxy
- `MAIL_MAILER=log` - Mail driver (currently logging only)
### Traefik Labels (docker-compose.yml)
```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.invoiceninja.rule=Host(`invoice.hyperthrive.io`)"
- "traefik.http.routers.invoiceninja.entrypoints=websecure"
- "traefik.http.routers.invoiceninja.tls.certresolver=letsencrypt"
- "traefik.http.services.invoiceninja.loadbalancer.server.port=80"
- "traefik.docker.network=traefik"
```
## Troubleshooting
### Permission Denied Errors
If the app container fails with "Permission denied" creating directories:
```bash
ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
docker compose down && \
sudo chown -R 1500:1500 docker/app && \
docker compose up -d"
```
### Database Connection Issues
Check database is healthy:
```bash
ssh jared@15.204.247.153 "docker inspect invoiceninja-db-1 --format='{{.State.Health.Status}}'"
```
Should return `healthy`. If not, check logs.
### 502 Bad Gateway
Usually means the app container isn't running or PHP-FPM hasn't started:
1. Check app container status: `docker ps --filter name=invoiceninja-app-1`
2. Check app logs: `docker logs invoiceninja-app-1 --tail 100`
3. Look for PHP-FPM startup message: "ready to handle connections"
### SSL Certificate Issues
Traefik automatically handles SSL. If certificate issues occur:
1. Check Traefik logs: `docker logs traefik`
2. Verify DNS points to server: `dig invoice.hyperthrive.io`
3. Check Traefik dashboard for router/certificate status
### Queue Not Processing
The official stack includes queue workers via supervisord. Check they're running:
```bash
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 supervisorctl status"
```
Should show `queue-worker_00` and `queue-worker_01` as RUNNING.
## Migration History
This deployment uses the **official Invoice Ninja Docker stack** (as of 2025-10-14). Previous custom stack was replaced to align with upstream recommendations and simplify maintenance.
**Pre-migration backup location**: `~/backups/invoiceninja-pre-official/` on server (retained until deployment proven stable)
## References
- Official Docker Repository: https://github.com/invoiceninja/dockerfiles
- Invoice Ninja Docs: https://invoiceninja.github.io
- Server Profile: `profile.yaml`
- Configuration Template: `configs/invoiceninja-official-template.yml`