2
4
Fork
You've already forked slcl
1
A simple and lightweight cloud solution written in C99 plus POSIX.1-2008 extensions.
  • C 97.3%
  • CMake 2.6%
  • Makefile 0.1%
Find a file
Xavier Del Campo Romero 30e9bcc492
Report missing authentication
Previously, HTTP error 403 was returned if an unauthenticated user
attempted to access a file or directory inside /user/. However, this
error message confusing because, most often, it was caused by legitimate
users with missing or expired HTTP cookies. While the usual workaround
was to access /index.html and authenticate, this was too confusing to
some users.
2026年06月13日 09:38:00 +02:00
cmake Replace OpenSSL with libsodium and argon2id 2025年10月08日 22:55:44 +02:00
doc doc/user.png: Update according to status quo 2025年10月09日 16:37:39 +02:00
fdzipstream Implement directory download as ZIP 2025年10月08日 02:03:05 +02:00
libweb @e8e9b1b129 Bump libweb 2026年06月13日 09:32:08 +02:00
thumbnail Replace thumbnail Makefile with configure script 2026年02月13日 07:55:09 +01:00
.gitignore Replace thumbnail Makefile with configure script 2026年02月13日 07:55:09 +01:00
.gitmodules Import fdzipstream 2025年10月06日 23:04:38 +02:00
auth.c Bump libweb 2026年02月13日 07:55:07 +01:00
auth.h Apply slweb renaming to libweb 2023年10月11日 00:08:40 +02:00
cftw.c cftw.c: Call user function at the end for directories 2025年10月06日 16:28:59 +02:00
cftw.h Make search non-blocking 2025年09月24日 12:39:09 +02:00
CMakeLists.txt Fix installation for thumbnail 2025年10月09日 11:30:38 +02:00
configure configure: Re-configure subprojects if required 2026年02月13日 09:37:27 +01:00
crealpath.c Introduce crealpath 2025年09月24日 11:03:39 +02:00
crealpath.h Introduce crealpath 2025年09月24日 11:03:39 +02:00
hex.c Move decode_hex into its own file 2023年03月09日 01:14:10 +01:00
hex.h Move decode_hex into its own file 2023年03月09日 01:14:10 +01:00
jwt.c jwt.c: Use original base64 variant 2025年10月09日 09:42:26 +02:00
jwt.h Initial commit 2023年02月28日 01:43:56 +01:00
LICENSE Initial commit 2023年02月28日 01:43:56 +01:00
main.c Report missing authentication 2026年06月13日 09:38:00 +02:00
page.c Report missing authentication 2026年06月13日 09:38:00 +02:00
page.h Report missing authentication 2026年06月13日 09:38:00 +02:00
README.md README.md: Add packages for Alpine Linux 2026年02月13日 07:55:08 +01:00
style.c Implement directory paging 2024年08月28日 03:57:27 +02:00
style.h Allow admins to define their own stylesheet 2023年07月11日 01:49:12 +02:00
usergen.c Replace OpenSSL with libsodium and argon2id 2025年10月08日 22:55:44 +02:00
wildcard_cmp.c wildcard_cmp.c: Fix out-of-bounds cmp 2023年07月09日 05:54:56 +02:00
wildcard_cmp.h wildcard_cmp: Allow case-insensitive searches 2023年06月06日 03:48:50 +02:00
zip.c zip.c: Fix endless loop on empty archives 2025年10月10日 09:40:34 +02:00
zip.h Implement directory download as ZIP 2025年10月08日 02:03:05 +02:00

slcl, a simple and lightweight cloud

slcl is a simple and lightweight implementation of a web file server, commonly known as "cloud storage" or simply "cloud", written in C99 plus POSIX.1-2008 extensions.

Screenshots

Screenshot of slcl's login page

Screenshot of an example user directory

Disclaimer

Intentionally, slcl does not share some of the philosophical views from the suckless project. However, it still strives towards portability, minimalism, simplicity and efficiency.

Features

  • Private access directory with file uploading, with configurable quota.
  • Read-only public file sharing.
  • Download directories as .zip files.
  • Uses libweb, a tiny web framework.
  • A simple JSON file as the credentials database.
  • No JavaScript.
  • Thumbnail generation can be optionally provided via a separate application and enabled by slcl via a command line option. Inter-process communication is achieved via a named pipe.

TLS

In order to maintain simplicity and reduce the risk for security bugs, slcl does not implement TLS support. Instead, this should be provided by a reverse proxy, such as caddy.

Root permissions

slcl is expected to listen to connections from any port number so that root access is not required. So, in order to avoid the risk for security bugs, please do not run slcl as root.

Encryption

Since no client-side JavaScript is used, files are uploaded unencrypted to slcl. If required, encryption should be done before uploading e.g.: using gpg.

Requirements

  • A POSIX environment.
  • libsodium.
  • cJSON >= 1.7.15.
  • ZLIB.
  • dynstr (provided as a git submodule by libweb).
  • libweb (provided as a git submodule).
  • fdzipstream (provided as a git submodule).
  • ImageMagick >= 6.0 (optional, for thumbnail only).
  • CMake (optional).

Ubuntu / Debian

Mandatory packages

sudo apt install build-essential libcjson-dev libsodium-dev zlib1g-dev

Optional packages

sudo apt install cmake libmagickcore-6.q16-dev

Alpine Linux

Mandatory packages

apk add make gcc musl-dev libsodium-dev cjson-dev zlib-dev

Optional packages

apk add cmake

Unfortunately, ImageMagick6, which is required by the thumbnail generation tool, might not be available from Alpine Linux's repositories.

How to use

Build

Two build environments are provided for slcl - feel free to choose any of them:

slcl can be built using the standard build process:

Make

$ ./configure
$ make

To enable the thumbnail generation program:

$ ./configure --thumbnail
$ make

CMake

$ cmake -B build
$ cmake --build build/

To enable the thumbnail generation program:

$ cmake -B build -DTHUMBNAIL=ON
$ cmake --build build/

Setting up

slcl consumes a path to a directory with the following tree structure:

.
├── db.json
├── public
└── user

Where:

  • db.json is the credentials database. Details are explained below.
    • Note: slcl creates a database with no users if not found, with file mode bits set to 0600.
  • public is a directory containing read-only files that can be accessed without authentication. Internally, they are implemented as simlinks to other files.
    • Note: slcl creates this directory if it does not exist, with directory mode bits set to 0700.
  • user is a directory containing user directories, which in turn contain anything users put into them.
    • Note: slcl creates this directory if it does not exist, with directory mode bits set to 0700.

Note: slcl creates the given directory if it does not exist.

Generated thumbnails are stored into another directory, namely thumbnails, which is automatically created with directory mode bits set to 0700.

.
├── db.json
├── public
├── thumbnails
└── user

A more complete example:

.
├── db.json
├── public
│  └── 44e03ab1bc3b0eff1567c76619186596 -> user/alice/file.jpg
├── thumbnails
│ ├── alice
│ │  └── file.jpg
│ └── john
└── user
 ├── alice
 │  └── file.jpg
 └── john
 └── file2.txt

Credentials database

slcl reads credentials from the db.json database, with the following schema:

{
 "users": [{
 "name":	"...",
 "password":	"...",
 "salt":	"...",
 "key":	"...",
 "quota": "..."
 }]
}

usergen is an interactive program that consumes a directory, a username, a password and, optionally, a user quota in MiB. A salt is randomly generated using openssl and passwords are hashed multiple times beforehand - see usergen and auth.c for further reference. Also, a random key is generated that is later used to sign HTTP cookies.

Then, usergen appends a JSON object to the users JSON array in the db.json file located inside the given directory. Also, usergen creates the user directory inside the user/ directory.

When users authenticate from a web browser, slcl sends a SHA256HMAC-signed JSON Web Token, using the random key generated by usergen. No session data is kept on the server.

Running

To run slcl, simply run the executable with the path to a directory including the files listed above. By default, slcl will listen to incoming connections on a random TCP port number. To set a specific port number, use the -p command line option. For example:

slcl -p 7822 ~/my-db/

slcl requires a temporary directory where files uploaded by users are temporarily stored until moved to the user directory. By default, slcl attempts to retrieve the path to the temporary directory by inspecting the TMPDIR environment variable, and falls back to /tmp if undefined.

If a custom temporary directory is required, it can be defined via command line option -t. For example:

slcl -t ~/my-tmp -p 7822 ~/my-db

Note: system-level temporary directories such as /tmp might reside on a filesytem different than the one where the database resides. This would force slcl to copy the contents from uploaded files from the temporary directory to the database, which might be an expensive operation. Therefore, in order to avoid expensive copies, define a custom temporary directory that resides on the same filesystem.

Thumbnail generation and rendering

Optionally, slcl displays thumbnails when listing a directory, if available from the thumbnails/ directory. In order to update these thumbnails when files are added/removed to/from the database, a separate application must be executed. See its README.md for further reference.

slcl provides the -F command line option to enable the use of a named pipe that shall be used by the thumbnail generation tool.

Why this project?

Previously, I had been recommended Nextcloud as an alternative to proprietary services like Dropbox. Unfortunately, despite being a very flexible piece of software, Nextcloud is way too heavy on resources, specially on lower end hardware such as the Raspberry Pi 3:

  • It uses around 30% RAM on my Raspberry Pi 3, configured with 973 MiB of RAM, and of course it gets worse with several simultaneous users.
  • Simple operations like searching and previewing files cause large amounts of I/O and RAM usage, so much that it locks the whole server up more often than not.
  • Nextcloud pages are bloated. Even the login page is over 15 MiB (!).
  • Requires clients to run JavaScript, which also has a significant performance penalty on the web browser. Also, some users do not feel comfortable running JavaScript from their web browsers, and thus prefer to disable it.

After years of recurring frustration as a Nextcloud administrator and user, I looked for alternatives that stripped out most of the unneeded bloat from Nextcloud, while providing the required features listed above. However, I could not find any that fit them, so I felt challenged to design a new implementation.

On the other hand, command line-based solutions like rsync might not be as convenient for non-technical people, compared to a web browser, or might not be even available e.g.: phones.

License

slcl, a simple and lightweight cloud.
Copyright (C) 2023-2025 Xavier Del Campo Romero
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

Also, see LICENSE.