{"id":46641377,"url":"https://github.com/polaco1782/share2me","last_synced_at":"2026-04-01T17:59:38.699Z","repository":{"id":342136339,"uuid":"1172232280","full_name":"polaco1782/share2me","owner":"polaco1782","description":"Share2Me is a secure file sharing daemon","archived":false,"fork":false,"pushed_at":"2026-03-05T03:03:28.000Z","size":71,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-05T04:13:51.168Z","etag":null,"topics":["file","https","privacy","server","sharing","temporary"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/polaco1782.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-04T04:33:14.000Z","updated_at":"2026-03-05T03:03:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/polaco1782/share2me","commit_stats":null,"previous_names":["polaco1782/share2me"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/polaco1782/share2me","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polaco1782%2Fshare2me","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polaco1782%2Fshare2me/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polaco1782%2Fshare2me/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polaco1782%2Fshare2me/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/polaco1782","download_url":"https://codeload.github.com/polaco1782/share2me/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polaco1782%2Fshare2me/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30243534,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:58:18.660Z","status":"online","status_checked_at":"2026-03-08T02:00:06.215Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["file","https","privacy","server","sharing","temporary"],"created_at":"2026-03-08T03:01:07.821Z","updated_at":"2026-04-01T17:59:38.687Z","avatar_url":"https://github.com/polaco1782.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Share2Me\n\n![Share2Me web UI](screenshot.png)\n\nShare2Me is a self-hosted file sharing server you run on your own machine or server. Once it's running, you get a private link for every file you upload — no accounts, no cloud service, no file size limits beyond your own disk space.\n\nEverything runs over HTTPS. A TLS certificate is generated automatically on the first launch, so you can get going with zero configuration.\n\n## What you can do with it\n\n- **Upload from the browser** — open the web UI, pick a file, and get a shareable link instantly.\n- **Upload from the terminal** — use `curl` to push files directly and get the link back in one command.\n- **Single-use links** — mark a file as \"single download\" and it's permanently deleted the moment someone downloads it.\n- **Expiring links** — set a time limit on any upload (e.g. 5 minutes, 2 hours, 3 days). The file disappears automatically once the time is up.\n- **End-to-end encryption** — tick one checkbox to encrypt files in the browser before they leave your machine. The server only ever sees ciphertext; the key never travels over the network.\n- **Your own domain with a real certificate** — point Share2Me at your domain and let it get a free Let's Encrypt certificate automatically.\n- **HTTP → HTTPS redirect** — anyone who visits the plain HTTP address is silently redirected to HTTPS.\n\n## Getting a pre-built binary\n\nEvery release has a ready-to-run Linux binary attached — no compiler needed. Go to the [Releases page](../../releases/latest), download `share2me-\u003cversion\u003e-linux-x86_64`, make it executable, and run it:\n\n```bash\nchmod +x share2me-v1.0.0-linux-x86_64\n./share2me-v1.0.0-linux-x86_64\n```\n\nThe binary is statically linked and has no runtime dependencies.\n\n## Building from source\n\nYou need CMake (≥ 3.20) and a C++20 compiler. Everything else is downloaded automatically during the build.\n\n```bash\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j$(nproc)\n```\n\nThe result is a single binary at `build/share2me`. Copy it anywhere you like.\n\n\u003e **Let's Encrypt support** is compiled in automatically if `libcurl` is available at build time. The final binary has no dependency on `libcurl` — it's only needed on the machine where you compile. Without it the server works fine with a self-signed or manually supplied certificate.\n\n## Releases \u0026 CI\n\nGitHub Actions will build, strip, and attach the binary to the release automatically. Release notes are generated from the commits since the previous tag.\n\n[Releases page](https://github.com/polaco1782/share2me/releases)\n\n## Running\n\n```bash\n# Quickstart — HTTPS on port 8443, self-signed certificate, ready immediately\n./build/share2me\n\n# Use standard ports (requires root or CAP_NET_BIND_SERVICE)\n./build/share2me --port 443 --http-port 80\n\n# Use a certificate you already have\n./build/share2me --domain example.com --cert /etc/ssl/example.crt --key /etc/ssl/example.key\n\n# Get a free Let's Encrypt certificate automatically (port 80 must be reachable from the internet)\n./build/share2me --domain example.com --email you@example.com --acme\n\n# Test Let's Encrypt integration without burning your rate limit\n./build/share2me --domain example.com --email you@example.com --acme --staging\n\n# Turn off the HTTP redirect entirely\n./build/share2me --http-port 0\n```\n\nThen open `https://localhost:8443` in your browser.\n\n### All options\n\n| Flag | Default | What it does |\n|------|---------|--------------|\n| `--port PORT` | `8443` | HTTPS port to listen on |\n| `--http-port PORT` | `8080` | HTTP port used for redirects and Let's Encrypt challenges (`0` = off) |\n| `--cert FILE` | `cert.pem` | Path to your TLS certificate |\n| `--key FILE` | `key.pem` | Path to your TLS private key |\n| `--domain NAME` | `localhost` | Your hostname (used in the certificate and in generated links) |\n| `--acme` | off | Obtain a certificate from Let's Encrypt automatically |\n| `--email EMAIL` | — | Your email address (required when using `--acme`) |\n| `--staging` | off | Use Let's Encrypt's test environment (certificate won't be trusted by browsers) |\n| `--sandbox` | off | Lock the process inside a chroot jail (requires root) |\n| `--user NAME` | — | Drop privileges to this system user after startup (requires root) |\n\n## Uploading files\n\n### From the browser\n\n1. Open `https://\u003chost\u003e:\u003cport\u003e` in your browser.\n2. Pick a file.\n3. Optionally turn on **Single-time download** or set an **expiry time**.\n4. Optionally tick **End-to-end encrypted 🔒 E2EE** to encrypt the file in your browser before uploading (see below).\n5. Click **Upload** and copy the link.\n\n### From the terminal\n\n```bash\n# Upload a file and print the share link\ncurl -kT photo.jpg https://localhost:8443/photo.jpg\n\n# Single-use link — file is gone after the first download\ncurl -kT report.pdf \"https://localhost:8443/report.pdf?single\"\n\n# Link that expires in 2 hours\ncurl -kT notes.txt \"https://localhost:8443/notes.txt?expire=2h\"\n\n# Both — single-use and expiring in 1 day\ncurl -kT archive.zip \"https://localhost:8443/archive.zip?single\u0026expire=1d\"\n\n# Save the link to a variable\nurl=$(curl -skT video.mp4 https://localhost:8443/video.mp4)\necho \"Share this: $url\"\n```\n\nExpiry values use a number followed by a unit: `m` (minutes), `h` (hours), `d` (days), `y` (years).\n\nDrop the `-k` flag if you're using a trusted certificate (Let's Encrypt or your own CA).\n\n## The share link\n\nEvery upload gets a unique, short link — for example `https://yourhost:8443/a1b2c3d4e5`. Anyone with the link can download the file. There are no passwords and no accounts. Keep the link private if you want the file to stay private.\n\n## End-to-end encryption (E2EE)\n\nWhen the **End-to-end encrypted** checkbox is ticked on the upload form, the file is encrypted entirely inside your browser using the Web Crypto API before a single byte is sent to the server.\n\n### How it works\n\n**Upload**\n\n1. The browser generates a fresh 256-bit AES-GCM key using `crypto.subtle.generateKey`.\n2. The file is split into 1 MB chunks. Each chunk is encrypted with its own random 12-byte IV:\n   ```\n   [4-byte chunk length (big-endian)] [12-byte IV] [ciphertext]\n   ```\n3. The resulting encrypted blob is uploaded to the server via the normal `POST /upload` path. The server stores opaque ciphertext — it has no access to the key or the plaintext.\n4. The raw key is base64-encoded and embedded in the **URL fragment** together with the original filename:\n   ```\n   https://yourhost/d/a1b2c3d4e5#k=\u003cbase64-key\u003e\u0026n=photo.jpg\n   ```\n\n**Why the fragment?** The `#fragment` part of a URL is a browser-only concept. It is never included in the HTTP request sent to the server, so the key is mathematically impossible for the server to observe.\n\n**Download**\n\n1. The recipient opens the share link. The browser fetches the ciphertext from `/a1b2c3d4e5` (server sees a normal token request).\n2. The key is read from `location.hash` — this happens entirely in JavaScript, never on the server.\n3. Each frame is decrypted in order with `crypto.subtle.decrypt`.\n4. The assembled plaintext is offered to the recipient as a browser download, named with the original filename stored in the fragment.\n\n### What the server stores\n\n| Field | Value |\n|---|---|\n| File data | AES-GCM ciphertext (opaque bytes) |\n| Metadata | Token, ciphertext SHA-256, original filename, single-dl/expiry flags, `encrypted: true` |\n| Encryption key | **Never stored — exists only in the share URL** |\n\n### Compatibility with other features\n\n- **`curl` / CLI uploads** — E2EE is a browser-only feature. `curl -T` uploads are always plaintext.\n\n### Security properties\n\n- The server operator cannot read encrypted files, even with full disk access.\n- Revocation is still possible: delete the token from `data/` and the ciphertext is gone, making the key in the URL useless.\n- Losing the share URL means losing the key — there is no recovery path.\n\n## Privacy \u0026 security\n\n**Nobody can browse your files.** There is no file listing, no index page, and no way to discover what has been uploaded. The only way to reach a file is to know its exact link.\n\nEach link contains a randomly generated token (e.g. `a1b2c3d4e5`). There are over a trillion possible tokens, so guessing one is not a realistic attack. If you keep the link to yourself, the file is effectively private.\n\nA few additional layers back this up:\n\n- **HTTPS only** — all traffic is encrypted. The plain-HTTP server exists solely to redirect browsers to HTTPS; it never serves files.\n- **End-to-end encryption** — when E2EE is enabled at upload time, the server only ever stores ciphertext. The key lives solely in the share URL fragment and never touches the server.\n- **No enumeration** — every request that doesn't match a valid, known token gets a `403 Forbidden` response. There is no way to probe the server to find out what files exist.\n- **Integrity verification** — a SHA-256 checksum is stored at upload time and re-checked on every download. If a file is tampered with on disk, the download is refused.\n- **Self-destructing links** — single-use links delete the file the instant it is downloaded. Expiring links are removed automatically once their time is up, even if nobody ever downloads them.\n- **Optional sandbox** — when started with `--sandbox`, the process is locked inside a chroot jail and (with `--user`) drops to a low-privilege system account, so a hypothetical server compromise cannot reach the rest of the filesystem.\n\nThe short version: share the link only with the people you trust, and the file is only accessible to them.\n\n## TLS certificates\n\nOn the very first run, if no certificate files are found, Share2Me generates a self-signed certificate automatically. It covers the configured domain, `localhost`, and `127.0.0.1`, and is valid for 10 years. You'll get a browser warning the first time because the certificate is self-signed — that's expected. You can dismiss it or, for a trusted certificate, use Let's Encrypt via `--acme`.\n\nTo swap the certificate at any time, just delete `cert.pem` and `key.pem` and restart — a new one will be generated — or point `--cert` and `--key` at your own files.\n\n## File storage\n\nAll uploaded files are kept in a `data/` directory next to the binary. Each file gets its own metadata record that tracks the original filename, a SHA-256 checksum, and any expiry or single-download settings. The checksum is verified on every download to ensure the file hasn't been corrupted. Expired files are cleaned up automatically in the background.\n\n## License\n\nShare2Me is released under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolaco1782%2Fshare2me","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolaco1782%2Fshare2me","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolaco1782%2Fshare2me/lists"}