🍓🖼️🍹 A small thing where I can upload a file and get a link back. https://media.strawmelonjuice.com/
TypeScript 38.9%
Gleam 34.4%
Rust 21.9%
Just 2.6%
Nix 1.2%
Dockerfile 0.7%
CSS 0.2%
Shell 0.1%
74 1 0

Clone this repository

https://tangled.org/strawmelonjuice.com/mediasjuice https://tangled.org/did:plc:jgtfsmv25thfs4zmydtbccnn/mediasjuice
git@knot.strawmelonjuice.com:strawmelonjuice.com/mediasjuice git@knot.strawmelonjuice.com:did:plc:jgtfsmv25thfs4zmydtbccnn/mediasjuice

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

Strawmediajuice 🍓🖼️🍹#

Welcome to Strawmediajuice!

This project is a lightweight and user-friendly file-sharing application. It allows users to upload files, manage their storage, and share files or artifacts via unique links.

v2.0.0 roadmap#

Version 2.0.0 will no longer ship with a server written in TypeScript, instead, Rust with the Rocket framework should make it both easier to maintain and stronger for future trials.

Implemented in Rust:#

  • Dashboard (/) serving static HTML
  • File serving (/file/<id>) with filename validation
  • Authentication (/api/auth) with session management
  • Session destruction (/api/session/destroy)
  • Simple file upload (/api/upload) with quota checking
  • Simple redirect from (/favicon.ico) to the strawmelonjuice.png file
  • User info retrieval from (/api/user/fetch)

Missing from Rust:#

  1. /api/files - File Listing

    • Lists all files for authenticated users
    • Admins see all files, regular users see only their own
    • Returns file sizes in MB
  2. /api/files/delete - File Deletion

    • Deletes files with permission checking
    • Updates user quotas
    • Cleans up physical files and directories
  3. /api/upload-streamed - WebSocket Upload

    • Handles large file uploads via WebSocket
    • Chunks data to avoid memory issues
    • Real-time quota validation during upload
  4. Automatic Sample File Creation

    • TS version downloads strawmelonjuice.png from strawmelonjuice.com
    • Rust version doesn't have this initialization

New features#

Some planned features never made it from the drawing board to the TypeScript version. The Rust rewrite allows for more features to be written into the api for version 2.0.0.

  1. Portal View for Files (/file/<id>/portal)

    • There's a todo!() for the respond_with_portal_html function
    • Should display file info with embed support for media files
  2. Admin panel (multiple api's missing, frontend missing)

    • An admin panel showable to users who are admin according to /api/user/fetch. Allows management, disabling (not removal), reset (deletes all files in ownership) or creation of other users, and server configuration. File management is still done on the file list, as admins can still see all files and their owners.
  3. Repository files (/release/<packagename>/, /api/upload-streamed)

    • Users claim a repository and own it, only owners and admins can alter (upload/remove/etc.) claimed repository.
    • Allows for 'versions' including two featured versions which are displayed at the top.
    • Claiming is done by uploading a file with filename <repositoryname>/<version>/<filename> to the server. Repository uploads might be unavailable for the web panel until a next release, but I am also thinking of a CLI, which would be very suitable and might even support doing this from the https://forge.strawmelonjuice.com CI.
    • Files with the same version and filename within a repository are overwritten.
    • Repository file uploads do not close when 100% is transmitted, instead they send a DONE, and await the server's response.
  4. Deploy (/pages/<username>/<repositoryname>-> might be aliased, /api/upload-streamed)

    • Builds on earlier statements from repository files.
    • Uploading <repositoryname>/deploy.zip turns an upload into a deployment. The deploy.zip is then unpacked, it must contain an ./index.html file, regardless of file content. If not, the upload is rejected.

Features:#

  • File Upload: Upload files securely and receive a unique link for sharing.
  • Authentication: Uploads are only possible by authenticated users. (no free signups)
  • File Management: List, download, and delete files.
  • Admin Controls: Manage user quotas and monitor storage usage.
  • Dashboard: A simple web interface for managing files.

Getting Started (dev mode, use the docker image for real use cases!)#

  1. Clone the repository:

    git clone https://git.strawmelonjuice.com/strawmelonjuice/strawmediajuice.git
    cd strawmediajuice
    
  2. Get the dependencies. mise i or nix development work, but if you'd want to install them in other ways, see the mise.toml file for your list of dependencies.

  3. Start the application:

    just dev
    
  4. Access the dashboard at http://localhost:3000.

Environment Variables#

To configure the application, set the following environment variables:

Variable name Description If not set
PORT The port on which the server will run. default: 3000
INIT_USERNAME The username for the initial admin account. Will prompt on first run.
INIT_PASSWORD The password for the initial admin account. will prompt on first run.
LOG_TO_FILE Wether to log to the strawmediajuice.log file in the data directory. will assume enabled. To disable set to 'false' or 0
EXPAND_TERMSIZE Wether to expand the terminal size for logging purposes. Due to usually running in docker, the application usually limits itself to 100 cols, to expand the width of the terminal, set this setting will assume disabled. To enable set to 'a number'

You can later create users by going into /app/ on the docker image and running bun ./scripts/user_add.ts, then answering the prompted information.

Data Persistence#

To ensure that uploaded files and database data are not lost, make sure to mount the data directory as a volume when deploying the application. This is especially important for Docker and Kubernetes deployments.

Docker Example#

volumes:
  - ./data:/app/data

Kubernetes Example#

volumeMounts:
  - name: data-volume
    mountPath: /app/data
volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: data-pvc

Docker Deployment#

The application is available as a Docker image on Docker Hub: strawmelonjuice/strawmediajuice.

Running with Docker CLI#

docker run -d \
    -p 3000:3000 \
    -e PORT=3000 \
    -e INIT_USERNAME=admin \
    -e INIT_PASSWORD=securepassword \
    -v $(pwd)/data:/app/data \
    strawmelonjuice/strawmediajuice:latest

Example docker-compose.yml#

version: "3.8"
services:
  strawmediajuice:
    image: strawmelonjuice/strawmediajuice:latest
    ports:
      - "3000:3000"
    environment:
      - PORT=3000
      - INIT_USERNAME=admin
      - INIT_PASSWORD=securepassword
    volumes:
      - ./data:/app/data

Kubernetes Deployment#

You can also deploy the application using Kubernetes. Here's an example manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: strawmediajuice
spec:
  replicas: 1
  selector:
    matchLabels:
      app: strawmediajuice
  template:
    metadata:
      labels:
        app: strawmediajuice
    spec:
      containers:
        - name: strawmediajuice
          image: strawmelonjuice/strawmediajuice:latest
          ports:
            - containerPort: 3000
          env:
            - name: PORT
              value: "3000"
            - name: INIT_USERNAME
              value: "admin"
            - name: INIT_PASSWORD
              value: "securepassword"
          volumeMounts:
            - name: data-volume
              mountPath: /app/data
      volumes:
        - name: data-volume
          persistentVolumeClaim:
            claimName: data-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: strawmediajuice
spec:
  selector:
    app: strawmediajuice
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

API Endpoints#

  • POST /api/upload: Upload a file.
  • GET /api/upload-streamed: Upload a file via websocket stream.
  • POST /api/auth: Authenticate a user.
  • POST /api/files: List files for a user.
  • POST /api/files/delete: Delete a file.

Contributing#

Feel free to open issues or submit pull requests to improve the project. Contributions are always welcome!


Happy sharing! 🚀