1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# nanobbs, a tiny forums software
`nanobbs` is a simple and lightweight implementation of a forums software,
commonly known as "bulletin board software" or simply "BBS", written in C99
plus POSIX.1-2008 extensions.
## Disclaimer
Intentionally, `nanobbs` does not share some of the philosophical views from the
[suckless project](https://suckless.org). However, it still strives towards
portability, minimalism, simplicity and efficiency.
## Features
- No JavaScript.
- Typical forums software features: categories, sections, topics and posts.
- Create/delete users from the web interface.
- Uses [`libweb`](https://gitea.privatedns.org/xavi/libweb), a tiny web framework.
- Uses [`libsodium`](https://www.libsodium.org/) as its cryptography backend.
- Uses [SQLite](https://sqlite.org/) as its database backend.
### TLS
In order to maintain simplicity and reduce the risk for security bugs, `nanobbs`
does **not** implement TLS support. Instead, this should be provided by a
reverse proxy, such as [`caddy`](https://caddyserver.com/).
### Root permissions
`nanobbs` 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 `nanobbs` as `root`**.
## Requirements
- A POSIX environment.
- [`libsodium`](https://www.libsodium.org/).
- [SQLite](https://sqlite.org/) >= 3.0.0 (tentative).
- [`dynstr`](https://gitea.privatedns.org/xavi/dynstr)
(provided as a `git` submodule by `libweb`).
- [`libweb`](https://gitea.privatedns.org/xavi/libweb)
(provided as a `git` submodule).
- CMake (optional).
### Ubuntu / Debian
#### Mandatory packages
```sh
sudo apt install build-essential libsqlite3-dev libsodium-dev
```
#### Optional packages
```sh
sudo apt install cmake
```
## How to use
### Build
Two build environments are provided for `nanobbs` - feel free to choose any of
them:
- A [`configure`](configure) POSIX shell and mostly POSIX-compliant
[`Makefile`](Makefile).
- A [`CMakeLists.txt`](CMakeLists.txt).
`nanobbs` can be built using the standard build process:
#### Make
```sh
$ ./configure
$ make
```
#### CMake
```sh
$ cmake -B build
$ cmake --build build/
```
### Setting up
`nanobbs` consumes a path to a directory with the following tree structure:
```
.
├── nanobbs.db
├── style.css
└── TERMS
```
Where:
- `nanobbs.db` is the SQLite database.
- **Note:** `nanobbs` creates a database with one administrator account,
namely `admin`, if not found, with file mode bits set to `0600`.
- `style.css` is the site stylesheet. It can be freely modified.
- **Note:** `nanobbs` creates a default stylesheet file, if not found.
- `TERMS` is a text file containing the terms of service for the instance.
It can be freely modified.
- **Note:** `nanobbs` creates a default terms file, if not found.
**Note:** `nanobbs` creates the given directory if it does not exist.
### Running
To run `nanobbs`, simply run the executable with the path to a directory including
the files listed above. By default, `nanobbs` 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:
```sh
nanobbs -p 7822 ~/my-db/
```
`nanobbs` requires a temporary directory where files uploaded by users are
temporarily stored until moved to the user directory. By default, `nanobbs`
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:
```sh
nanobbs -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 `nanobbs` 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.
## Why this project?
When looking up a forums software for
[Speed Dreams](https://www.speed-dreams.net/), traditional forums software
solutions had been considered, such as [phpBB](https://www.phpbb.com/),
[myBB](https://mybb.com/) or [Discourse](https://www.discourse.org/),
yet raised concerns related to perceived software bloat and/or excessive
use of client-side JavaScript.
As of the time of this writing, there was no forums software written in C
other than `nanobbs`,
[according to Wikipedia](https://en.wikipedia.org/wiki/Comparison_of_Internet_forum_software).
Since [`slcl`](https://gitea.privatedns.org/xavi/slcl), another project with
the same philosophy, was motivated by similar goals back then, `nanobbs` was seen
as a good opportunity to show how a solution written in C can be both simple,
efficient and safe.
## License
```
nanobbs, a tiny forums software.
Copyright (C) 2025-2026 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`](LICENSE).
|