Compare commits
3 Commits
ce1fa0b801
...
53dd416c17
| Author | SHA1 | Date | |
|---|---|---|---|
| 53dd416c17 | |||
| 31da68b6c1 | |||
| 2ecfda256b |
22
Dockerfile
Normal file
22
Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
FROM ghcr.io/gleam-lang/gleam:v1.14.0-erlang-alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache elixir git libstdc++ openssl
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY gleam.toml manifest.toml ./
|
||||||
|
COPY src/ ./src/
|
||||||
|
|
||||||
|
RUN gleam deps download && gleam build --target erlang
|
||||||
|
|
||||||
|
RUN adduser -D -H spasteg && chown -R spasteg:spasteg /app
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
USER spasteg
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["gleam", "run", "--target", "erlang", "--", "--no-halt"]
|
||||||
52
README.md
52
README.md
@@ -11,6 +11,14 @@ A secure, self-hostable "burn after reading" paste service with ephemeral storag
|
|||||||
- Fast and reliable
|
- Fast and reliable
|
||||||
- Written in Gleam (type-safe)
|
- Written in Gleam (type-safe)
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- Gleam: Type-safe language built upon the BEAM
|
||||||
|
- Web: Wisp framework + Mist HTTP server
|
||||||
|
- Frontend: Lustre for HTML rendering
|
||||||
|
- Storage: In-memory only (no persistence)
|
||||||
|
- Security: AES-256-GCM client-side encryption, CSRF tokens, rate limiting, security headers
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### SECRET_KEY_BASE (Required for Production)
|
### SECRET_KEY_BASE (Required for Production)
|
||||||
@@ -50,6 +58,29 @@ gleam run
|
|||||||
|
|
||||||
The server starts on `http://localhost:3000`.
|
The server starts on `http://localhost:3000`.
|
||||||
|
|
||||||
|
## Docker image+deployment
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t spasteg .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate a secure key
|
||||||
|
docker run -p 3000:3000 -e SECRET_KEY_BASE=$(openssl rand -base64 48) spasteg
|
||||||
|
```
|
||||||
|
|
||||||
|
**With custom port:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -p 8080:3000 -e SECRET_KEY_BASE=$(openssl rand -base64 48) -e PORT=3000 spasteg
|
||||||
|
```
|
||||||
|
|
||||||
|
The container exposes port 3000 and runs as a non-root user with a health check configured.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1. Visit `http://localhost:3000`
|
1. Visit `http://localhost:3000`
|
||||||
@@ -60,27 +91,6 @@ The server starts on `http://localhost:3000`.
|
|||||||
|
|
||||||
Note: the creator cannot see their post with the copied link (except in private browsing) - it would be burned immediately.
|
Note: the creator cannot see their post with the copied link (except in private browsing) - it would be burned immediately.
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
- **Gleam**: Type-safe language built upon the BEAM
|
|
||||||
- **Web**: Wisp framework + Mist HTTP server
|
|
||||||
- **Frontend**: Lustre for HTML rendering
|
|
||||||
- **Storage**: In-memory only (no persistence)
|
|
||||||
- **Security**: AES-256-GCM client-side encryption, CSRF tokens, rate limiting, security headers
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
- Pastes are client-side encrypted (AES-256-GCM) before being sent to server
|
|
||||||
- Server never sees the decryption key (stored in URL fragment after `#`)
|
|
||||||
- Data is stored **encrypted** in server memory only
|
|
||||||
- Data is **never written to disk**
|
|
||||||
- All data is lost on server restart
|
|
||||||
- CSRF protection via double-submit cookie pattern
|
|
||||||
- Rate limiting: 10 requests per IP (resets on server restart)
|
|
||||||
- Security headers: CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy
|
|
||||||
- 10MB maximum paste size limit
|
|
||||||
- Intended for ephemeral sharing only — do not store sensitive data
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the GNU General Public License v3.0 or later (GPLv3+). See the [LICENSE](LICENSE) file for details.
|
This project is licensed under the GNU General Public License v3.0 or later (GPLv3+). See the [LICENSE](LICENSE) file for details.
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ pub fn main() {
|
|||||||
secret_key_base,
|
secret_key_base,
|
||||||
)
|
)
|
||||||
|> mist.new
|
|> mist.new
|
||||||
|
|> mist.bind("0.0.0.0")
|
||||||
|> mist.port(3000)
|
|> mist.port(3000)
|
||||||
|> mist.start
|
|> mist.start
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user