{"id":17102640,"url":"https://github.com/igor47/smrs","last_synced_at":"2025-03-23T19:23:32.518Z","repository":{"id":145755590,"uuid":"345463496","full_name":"igor47/smrs","owner":"igor47","description":"a cgi-dispatched link shortener in rust","archived":false,"fork":false,"pushed_at":"2023-08-30T16:29:20.000Z","size":463,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-14T18:54:28.395Z","etag":null,"topics":["apache2","cgi","minimal","rust","self-hosted"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igor47.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-07T22:03:59.000Z","updated_at":"2024-10-20T00:28:47.000Z","dependencies_parsed_at":"2024-11-30T21:11:42.944Z","dependency_job_id":"c310e9ac-d8d2-44b5-85d6-b4c2d459677a","html_url":"https://github.com/igor47/smrs","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igor47%2Fsmrs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igor47%2Fsmrs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igor47%2Fsmrs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igor47%2Fsmrs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igor47","download_url":"https://codeload.github.com/igor47/smrs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245155165,"owners_count":20569664,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apache2","cgi","minimal","rust","self-hosted"],"created_at":"2024-10-14T15:29:39.299Z","updated_at":"2025-03-23T19:23:32.440Z","avatar_url":"https://github.com/igor47.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Docker Build](https://github.com/igor47/smrs/actions/workflows/publish.yaml/badge.svg)\n\n# SMRS\n\nThis repository contains the source code for a cgi-dispatched link shortener written in rust.\nYou can host this project in your own environment using the instructions below.\n\n## Why SMRS\n\nLinks on the web are getting increasingly more bloated.\nFriends don't send friends multi-line links!\nHowever, third-party link services are a privacy nightmare.\nBut mainly, I wanted to learn Rust and this seemed like a simple project.\n\n## Features\n\nThis project is meant to be minimal and simple.\nUser features:\n\n* Minimal, responsive UI\n* Simple API (see below)\n* Generates three-word short urls\n* Allows you to optionally pick your short url\n\nSoftware features:\n\n* We allow a real web server (Apache2) to handle TLS termination and static file serving.\n* We execute the rust binary via CGI to implement the API and interact with [sqlite](https://sqlite.org/index.html).\n* The front-end uses Apache's [SSIs](https://httpd.apache.org/docs/current/howto/ssi.html) to render static pages with a common header.\n* We use a little bit of [Alpine.js](https://alpinejs.dev/) for interactive elements.\n* There is no login, but you can see and set your own session cookie to keep track of your shortened links.\n## Screenshot\n\n![Screenshot](./screenshot.png)\n\n## Installation\n\nThe recommended way to install this project is to use the docker image.\nHowever, especially if you just want to use the API, you can also install the binary directly in your own web server.\n\n### Via Docker\n\nFirst, prepare a directory for the data file.\nIt must be owned by the user with UID 82 (www-data on Debian/Ubuntu).\n\n```bash\n$ mkdir -p ${STORAGE}/smrs/data\n$ sudo chown 82:82 ${STORAGE}/smrs/data\n```\n\nHere's an example docker-compose stanza:\n\n```yaml\n  smrs:\n    image: ghcr.io/igor47/smrs:v0.1.1\n    restart: unless-stopped\n    container_name: smrs\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.smrs.rule=Host(`example.com`,`www.example.com`)\"\n      - \"traefik.http.routers.smrs.tls=true\"\n      - \"traefik.http.routers.smrs.tls.certresolver=letsencrypt\"\n      - \"traefik.http.routers.smrs.entrypoints=https\"\n      - \"traefik.http.services.smrs.loadbalancer.server.port=8000\"\n    volumes:\n      - ${STORAGE}/smrs/data:/smrs/data\n```\n\nThis uses Traefik as a reverse proxy to the container port 8000.\nYou can use your own reverse proxy, or expose the port directly.\n\n### Via Binary\n\nClone the repository and build the binary:\n\n```bash\n$ cargo build --release\n```\n\nPut the file `target/release/smrs` somewhere in your web server's path.\nYou'll need to configure your server to run the binary as a CGI script.\nI use `apache2` inside the container.\nThe config file is in [conf/smrs.conf](https://github.com/igor47/smrs/blob/master/conf/smrs.conf) in this repo.\n\n## API\n\nThe rust binary implements the following API endpoints:\n\n* `GET /session` - returns the current session as `{ session: string }`\n* `POST /session` - sets the session cookie to the given value `{ session: string }`\n* `POST /save` - saves the URL at the given token (if not already in-use) `{ url: string, token: string }`\n* `GET /to/\u003ctoken` - redirects to the URL at the given token, or returns a `404`\n* `GET /list` - returns a list of all tokens and URLs saved by the current `session` as `{ links: [{ token: string, url: string, created_at: i32 }]`\n* `POST /forget` - marks the given token as deleted, or `404`: `{ token: string }`\n\n## Development\n\nTo run this project locally, you can install the `cargo make` tool and run the `devenv` task:\n\n```bash\n$ cargo make devenv\n```\n\nThe dev environment will be accessible at [localhost:8000/](http://localhost:8000).\nThis will bind-mount the `htdocs` dir into the container so you can just iterate on the code and reload.\nTo iterate on the rust binary, you can run the `iter` task, which will build the binary locally and copy into the container:\n\n```bash\n$ cargo make iter\n```\n\n## Pull Requests\n\nWelcome!\nBut keep in mind that this project is meant to be minimal.\nI will not accept PRs that add too many dependencies or features that I don't want.\n\n## License\n\nMIT.\nFeel free to fork and do what you want.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figor47%2Fsmrs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figor47%2Fsmrs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figor47%2Fsmrs/lists"}