{"id":13781874,"url":"https://github.com/daknob/eldim","last_synced_at":"2026-02-22T01:39:39.489Z","repository":{"id":57530184,"uuid":"119903447","full_name":"daknob/eldim","owner":"daknob","description":"A Secure File Upload Proxy","archived":false,"fork":false,"pushed_at":"2026-02-21T22:52:27.000Z","size":247,"stargazers_count":42,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-21T23:04:35.406Z","etag":null,"topics":["age","backup","encryption","google-cloud","google-cloud-platform","google-storage","google-storage-bucket","log","prometheus-metrics","proxy-server","storage"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daknob.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}},"created_at":"2018-02-01T22:51:57.000Z","updated_at":"2026-02-21T22:52:30.000Z","dependencies_parsed_at":"2024-01-15T20:54:52.060Z","dependency_job_id":"75a6b164-3996-451e-a235-c3c5d746e865","html_url":"https://github.com/daknob/eldim","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/daknob/eldim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daknob%2Feldim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daknob%2Feldim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daknob%2Feldim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daknob%2Feldim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daknob","download_url":"https://codeload.github.com/daknob/eldim/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daknob%2Feldim/sbom","scorecard":{"id":317464,"data":{"date":"2025-08-11","repo":{"name":"github.com/daknob/eldim","commit":"e7b06f0c73ff793b625e6a464ea92aaefb325e3b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build-release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/build-release.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/daknob/eldim/build-release.yml/main?enable=pin","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2024-3344 / GHSA-32gq-x56h-299c"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T00:33:28.879Z","repository_id":57530184,"created_at":"2025-08-18T00:33:28.880Z","updated_at":"2025-08-18T00:33:28.880Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29703227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T23:35:04.139Z","status":"ssl_error","status_checked_at":"2026-02-21T23:35:03.832Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["age","backup","encryption","google-cloud","google-cloud-platform","google-storage","google-storage-bucket","log","prometheus-metrics","proxy-server","storage"],"created_at":"2024-08-03T18:01:30.268Z","updated_at":"2026-02-22T01:39:39.472Z","avatar_url":"https://github.com/daknob.png","language":"Go","funding_links":[],"categories":["Integrations"],"sub_categories":[],"readme":"# eldim\nA Secure File Upload Proxy\n\n## Description\neldim is a web server that accepts file uploads from a particular set of\nhosts, and its job is to encrypt them, and then store them in an Object\nStorage backend system.\n\n![The eldim flow of data](docs/img/flow.svg)\n\nIt has a preconfigured ACL that only allows specific IP Addresses, or token\nbearers to access the file upload service. After a file is uploaded, it is\nencrypted, and then uploaded to a configured provider.\n\nIt has been designed to work as a standalone application, which means it must\nnot sit behind a proxy, but instead be exposed directly to the Internet.\n\n## Groups \u0026 Mailing Lists\nCurrently the project has two mailing lists, in Google Groups, that are used\nfor communication:\n\n### eldim-announce\nThe [eldim-announce](https://groups.google.com/forum/#!forum/eldim-announce)\ngroup is **recommended** for all users of eldim. It includes announcements\nfor new versions, a changelog, as well as breaking changes that may occur\nin the future. Moreover, it is the place that will be used for security\nannouncements in the future, if and when they come.\n\nThis is a very low volume list, and it is read-only. That is, only eldim\nupdates are posted there, and you cannot send e-mails to other members.\n\n### eldim-dev\nThe [eldim-dev](https://groups.google.com/forum/#!forum/eldim-dev) group\ntries to address that final point above, and it is the techincal mailing\nlist of the eldim project.\n\nThis group can be used to report problems, share news, exchange ideas, etc.\nBasically it exists for communication about technical matters related to\neldim, between the users, the contributors, or the developers.\n\n## Design Decisions\nThe design of eldim is data agnostic, and tries to push the relevant logic\nof all operations to the proper server. For example, the service itself does\nnot care what types of files are uploaded, or when they're uploaded, or what\nthey are. It simply receives a file and a file name, and then encrypts and\nuploads this file under a specific name to the Object Storage.\n\nIn eldim's configuration file you can add a list of hosts, as well as their\n(host)names, and eldim makes sure that all files uploaded from a particular\nhost will always have that host's name in their name. For example, files from\nthe host `mail.example.com`, will always have a file name starting with\n`mail.example.com/`.\n\nThe data collection part is left to the servers sending data to it. It is\nthem who decide what to send, when to send it, and what operations, such as\ncompression for example, must be applied to the file.\n\n## Security\nIn order for every server to be able to upload logs or backups to a central\nobject storage bucket, they need to have some secrets stored in them. For\nexample, in Swift, each server needs to have a username and an API key. This\nis something that is not really secure, as compromising any server would give\nfull access to the backup repository. An attacker could download files, delete\nfiles, change them, etc.\n\nIn eldim, the servers do not have any stored information, and instead just\nupload the files to a single server. This server is the one with the access,\nand can control what operations are being performed, and by whom.\n\nThe way eldim works, no server is allowed to mess with another server's files.\nServer `mail.example.com` cannot upload files as `ftp.example.com`, even if\nthey upload to the very same bucket. eldim automatically prepends all file\nuploads with the server hostname, which is inside its configuration file, and\nnot sent by the servers themselves.\n\nMoreover, eldim will reject files that already exist. If the file\n`mail.example.com/2018-01-01/mail.log.tgz` already exists in the object store,\nit will not allow for it to be overwritten. This check is in place to prevent\na hacked server from overwritting all previous log entries with empty data,\neffectively deleting everything.\n\nFinally, eldim works only over HTTPS. This decision is hard coded inside the\nserver itself, and cannot be changed by the configuration file. A code change\nis required. It is configured to only work with at least TLSv1.2, the only\ncurrently secure versions of TLS, but currently it may accept some more weak\nciphers and not only the most secure ones.\n\n### Encryption\nSince version v0.6.0, eldim uses [age](https://age-encryption.org/) for file\nencryption. It is a well defined protocol, with multiple implementations, a\nvery good CLI tool, and is already part of some operating system distributions.\nMore importantly, it is modern, well-designed, and opinionated, with one and\nonly one purpose in mind: encrypt files. It uses state of the art practices\nand algorithms, and is also very flexible.\n\nage is using asymmetric encryption, which means that eldim only needs to know\nabout the **public** keys in its configuration file, and never needs or has\naccess to the *private* keys. This vastly reduces the risk of a compromised\neldim server, as files uploaded cannot be decrypted by the attacker.\n\nWith age, eldim supports multiple public keys, so you can use more than one,\nand have the files encrypted with all of them. That means that files can be\ndecrypted with **any** of the keys. You can use this functionality to have\nbackup keys, or give access to multiple people, each one holding their own\nkey pair. Unfortunately, eldim currently does not support *M of N* so you\nneed to keep this in mind while threat modelling.\n\nTo generate an age keypair, you can use the `age-keygen` CLI tool. However,\na very nice feature is that eldim also supports SSH keys! You can use your\nRSA or Ed25519 SSH keys in addition to the age keys. A single eldim server\nsupports multiple keys, of different types.\n\n## How to run eldim\neldim runs as a daemon, since it has to listen for HTTPS requests\ncontinuously. For this reason, you need to ensure that the binary is\nrunning all the time. The recommended way of achieving this is through your\noperating system's startup / init system. If you are using `systemd`, a basic\nunit file is provided in this repository for you to use.\n\nAs with any software, it is **not** recommended to run eldim as `root`. For\nthis reason, you should create an `eldim` user. The included `systemd` unit\nfile assumes the `eldim` user exists in the system.\n\nYou can create such user by running:\n\n```bash\nsudo useradd -s /usr/sbin/nologin -r -M eldim\n```\n\nWhen executed, eldim has two command line flags that you can use to configure\nit before it even reads the configuration file. They are:\n\n* `-j`: When set, it will output all logs in JSON format, instead of plaintext\n* `-c`: The path to the configuration file\n\n## Metrics\nAs of `eldim v0.2.0`, eldim supports metrics exporting using\n[Prometheus](https://prometheus.io/). You can find more information about the\nmetrics currently supported and exported [here](docs/metrics.md).\n\n## Configuration\nIn order to read the full documentation on how to configure `eldim`, click\n[here](docs/config.md).\n\n## The HTTP API\nYou can find the full specification of the HTTP API of `eldim` by clicking\n[here](docs/api.md).\n\n## How to upload data from a server\nYou can basically upload files to eldim in any way you like, as long as you\nfollow the above API, but here are some examples. This code can be for example\nin a daily or weekly cron job:\n\n```bash\n# Compress nginx' access.log\ntar -zcf /tmp/nginx.access.log.tgz /var/log/nginx/access.log /var/log/nginx/access.log.1\n# Upload to eldim\ncurl -F filename=$(date +%F-%H-%M)/access.log -F file=@/tmp/nginx.access.log.tgz https://eldim.example.com/api/v1/file/upload/\n```\n\nThe `$(date +%F-%H-%M)` part will automatically print the date in the\n`2018-01-01-13-37` format (`YYYY-MM-DD-HH-MM`).\n\nIf you are testing eldim, you may use `-k` in `curl`, to skip certificate\nchecks, as you may be using a self-signed certificate. However, deploying\nthis to production without a trusted certificate is **not** recommended.\n\nFor production workloads, you may want to use the `--retry N` flag of `curl`,\nto retry the request up to `N` times, if it fails. It is recommended to also\nset the `--retry-connrefused` flag as well. You can combine the above with\n`--retry-delay X`, so `curl` will sleep `X` seconds between retries. Good\nvalues for `X` are eldim's domain TTL * 2, or something similar.\n\neldim is designed to work without placing trust on the file upload servers.\nIf, however, you want to not have to trust the eldim server either, you can\noptionally encrypt all data sent to eldim with `age` (or `gpg`). That way\neldim won't be able to decrypt them, but neither will the sender alone.\n\nTo encrypt files with `age`, use:\n\n```bash\ncat file.tgz | age -r \"AgeID\" \u003e out.tgz.enc\n```\n\nOf course, you need to replace \"AgeID\" with an age recipient address.\n\n## eldim Logs\nCurrently eldim logs a lot of information in detail. This is done on purpose\nand is not a debugging leftover. Since it is a tool that is related to\nsecurity, it is always good to have a lot of information to be able to go back\nto in case something happens.\n\nIt is totally normal for eldim to log up to 20 lines per successful upload\nrequest, or even more, depending on the configuration.\n\nDuring service startup, all information logged is related to actions and\nthe configuration file, and is in plain text. After the service is started,\nall logs start with a UUID. This is called the Request ID. During the\narrival of every request, eldim generates a unique identifier for this\nrequest. This identifier is included in every future log file entry that\nis related to this request.\n\nBy default eldim logs to `stdout` and `stderr`, so if you are using the\nprovided `systemd` unit file, all its logs will be available in `syslog`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaknob%2Feldim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaknob%2Feldim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaknob%2Feldim/lists"}