Initial commit with server startup infrastructure
Core infrastructure: - Uber fx dependency injection - Chi router with middleware stack - SQLite database with embedded migrations - Embedded templates and static assets - Structured logging with slog Features implemented: - Authentication (login, logout, session management, argon2id hashing) - App management (create, edit, delete, list) - Deployment pipeline (clone, build, deploy, health check) - Webhook processing for Gitea - Notifications (ntfy, Slack) - Environment variables, labels, volumes per app - SSH key generation for deploy keys Server startup: - Server.Run() starts HTTP server on configured port - Server.Shutdown() for graceful shutdown - SetupRoutes() wires all handlers with chi router
This commit is contained in:
179
README.md
Normal file
179
README.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# upaas
|
||||
|
||||
A simple self-hosted PaaS that auto-deploys Docker containers from Git repositories via Gitea webhooks.
|
||||
|
||||
## Features
|
||||
|
||||
- Single admin user with argon2id password hashing
|
||||
- Per-app SSH keypairs for read-only deploy keys
|
||||
- Per-app UUID-based webhook URLs for Gitea integration
|
||||
- Branch filtering - only deploy on configured branch changes
|
||||
- Environment variables, labels, and volume mounts per app
|
||||
- Docker builds via socket access
|
||||
- Notifications via ntfy and Slack-compatible webhooks
|
||||
- Simple server-rendered UI with Tailwind CSS
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Multi-user support
|
||||
- Complex CI pipelines
|
||||
- Multiple container orchestration
|
||||
- SPA/API-first design
|
||||
- Support for non-Gitea webhooks
|
||||
|
||||
## Architecture
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
upaas/
|
||||
├── cmd/upaasd/ # Application entry point
|
||||
├── internal/
|
||||
│ ├── config/ # Configuration via Viper
|
||||
│ ├── database/ # SQLite database with migrations
|
||||
│ ├── docker/ # Docker client for builds/deploys
|
||||
│ ├── globals/ # Build-time variables (version, etc.)
|
||||
│ ├── handlers/ # HTTP request handlers
|
||||
│ ├── healthcheck/ # Health status service
|
||||
│ ├── logger/ # Structured logging (slog)
|
||||
│ ├── middleware/ # HTTP middleware (auth, logging, CORS)
|
||||
│ ├── models/ # Active Record style database models
|
||||
│ ├── server/ # HTTP server and routes
|
||||
│ ├── service/
|
||||
│ │ ├── app/ # App management service
|
||||
│ │ ├── auth/ # Authentication service
|
||||
│ │ ├── deploy/ # Deployment orchestration
|
||||
│ │ ├── notify/ # Notifications (ntfy, Slack)
|
||||
│ │ └── webhook/ # Gitea webhook processing
|
||||
│ └── ssh/ # SSH key generation
|
||||
├── static/ # Embedded CSS/JS assets
|
||||
└── templates/ # Embedded HTML templates
|
||||
```
|
||||
|
||||
### Dependency Injection
|
||||
|
||||
Uses Uber fx for dependency injection. Components are wired in this order:
|
||||
|
||||
1. `globals` - Build-time variables
|
||||
2. `logger` - Structured logging
|
||||
3. `config` - Configuration loading
|
||||
4. `database` - SQLite connection + migrations
|
||||
5. `healthcheck` - Health status
|
||||
6. `auth` - Authentication service
|
||||
7. `app` - App management
|
||||
8. `docker` - Docker client
|
||||
9. `notify` - Notification service
|
||||
10. `deploy` - Deployment service
|
||||
11. `webhook` - Webhook processing
|
||||
12. `middleware` - HTTP middleware
|
||||
13. `handlers` - HTTP handlers
|
||||
14. `server` - HTTP server
|
||||
|
||||
### Request Flow
|
||||
|
||||
```
|
||||
HTTP Request
|
||||
│
|
||||
▼
|
||||
chi Router ──► Middleware Stack ──► Handler
|
||||
│
|
||||
(Logging, Auth, CORS, etc.)
|
||||
│
|
||||
▼
|
||||
Handler Function
|
||||
│
|
||||
▼
|
||||
Service Layer (app, auth, deploy, etc.)
|
||||
│
|
||||
▼
|
||||
Models (Active Record)
|
||||
│
|
||||
▼
|
||||
Database
|
||||
```
|
||||
|
||||
### Key Patterns
|
||||
|
||||
- **Closure-based handlers**: Handlers return `http.HandlerFunc` allowing one-time initialization
|
||||
- **Active Record models**: Models encapsulate database operations (`Save()`, `Delete()`, `Reload()`)
|
||||
- **Async deployments**: Webhook triggers deploy via goroutine with `context.WithoutCancel()`
|
||||
- **Embedded assets**: Templates and static files embedded via `//go:embed`
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Go 1.23+
|
||||
- golangci-lint
|
||||
- Docker (for running)
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
make fmt # Format code
|
||||
make lint # Run comprehensive linting
|
||||
make test # Run tests with race detection
|
||||
make check # Verify everything passes (lint, test, build, format)
|
||||
make build # Build binary
|
||||
```
|
||||
|
||||
### Commit Requirements
|
||||
|
||||
**All commits must pass `make check` before being committed.**
|
||||
|
||||
Before every commit:
|
||||
|
||||
1. **Format**: Run `make fmt` to format all code
|
||||
2. **Lint**: Run `make lint` and fix all errors/warnings
|
||||
- Do not disable linters or add nolint comments without good reason
|
||||
- Fix the code, don't hide the problem
|
||||
3. **Test**: Run `make test` and ensure all tests pass
|
||||
- Fix failing tests by fixing the code, not by modifying tests to pass
|
||||
- Add tests for new functionality
|
||||
4. **Verify**: Run `make check` to confirm everything passes
|
||||
|
||||
```bash
|
||||
# Standard workflow before commit:
|
||||
make fmt
|
||||
make lint # Fix any issues
|
||||
make test # Fix any failures
|
||||
make check # Final verification
|
||||
git add .
|
||||
git commit -m "Your message"
|
||||
```
|
||||
|
||||
The Docker build runs `make check` and will fail if:
|
||||
- Code is not formatted
|
||||
- Linting errors exist
|
||||
- Tests fail
|
||||
- Code doesn't compile
|
||||
|
||||
This ensures the main branch always contains clean, tested, working code.
|
||||
|
||||
## Configuration
|
||||
|
||||
Environment variables:
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `UPAAS_PORT` | HTTP listen port | 8080 |
|
||||
| `UPAAS_DATA_DIR` | Data directory for SQLite and keys | ./data |
|
||||
| `UPAAS_DOCKER_HOST` | Docker socket path | unix:///var/run/docker.sock |
|
||||
| `DEBUG` | Enable debug logging | false |
|
||||
| `SENTRY_DSN` | Sentry error reporting DSN | "" |
|
||||
| `METRICS_USERNAME` | Basic auth for /metrics | "" |
|
||||
| `METRICS_PASSWORD` | Basic auth for /metrics | "" |
|
||||
|
||||
## Running with Docker
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v upaas-data:/data \
|
||||
upaas
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user