Compare commits

..

9 Commits

Author SHA1 Message Date
1038e8ea1e add .touched files to ignores 2025-05-23 14:13:37 +03:00
17e231ed74 revise instructions 2025-05-23 13:35:54 +03:00
7f17d4c29e finalize docker setup
now fully works via docker \o/
2025-05-23 13:14:51 +03:00
4fa80aa8c7 VERY quick fix: randomize seed when making admin account 2025-05-23 05:41:38 +03:00
2ccacf12a3 use correct check in start script 2025-05-23 04:55:39 +03:00
0d7ed52679 NOT DONE YET - allow containerization
a bunch was restructured to make it amenable to docker.

it works fine, except when writing to the db. trying to log in (thus creating a session)
will have Lapis throw "attempt to write a readonly database"
2025-05-23 04:46:10 +03:00
af20b626d5 put db and static into data/ 2025-05-22 23:20:15 +03:00
ddad153875 argon2 experiment 2025-05-22 22:30:20 +03:00
74a0ae5027 fix infobox in user view 2025-05-22 22:30:14 +03:00
18 changed files with 105 additions and 87 deletions

8
.dockerignore Normal file
View File

@ -0,0 +1,8 @@
logs/
nginx.conf.compiled
.vscode/
.local/
data/db/*
secrets
secrets/.touched*
sass

11
.gitignore vendored
View File

@ -1,10 +1,9 @@
logs/
nginx.conf.compiled
db.*.sqlite
.vscode/
.local/
static/avatars/*
!static/avatars/default.webp
secrets.lua
.first_launch.*
data/db/*
secrets/secrets.lua
secrets/.touched*
data/static/avatars/*
!data/static/avatars/default.webp

16
Dockerfile Normal file
View File

@ -0,0 +1,16 @@
# HOW TO:
#
# docker compose up
#
# it exposes the data/ and secrets/ volumes in app root
#
FROM openresty/openresty:alpine-fat
RUN apk add --no-cache git make gcc g++ musl-dev libffi-dev openssl-dev sqlite-dev libsodium libsodium-dev imagemagick-dev openssl
WORKDIR /app
COPY . .
RUN eval "$(luarocks --lua-version=5.1 path)"
RUN luarocks --lua-version=5.1 build --only-deps
EXPOSE 8080
RUN chmod +x /app/start.sh
ENTRYPOINT ["/app/start.sh", "production"]

View File

@ -6,34 +6,43 @@ Released under [CNPLv7+](https://thufie.lain.haus/NPL.html).
Please read the [full terms](./LICENSE.md) for proper wording.
# installing & first time setup
1. first, install OpenResty. instructions for linux can be found [here](https://openresty.org/en/linux-packages.html).
2. then, install LuaJIT and Lua 5.1 (usually called `lua5.1` in package managers)
3. then, install [LuaRocks](https://luarocks.org) (prefer your package manager instead of a local install recommended by the guide)
4. add luarocks search dirs to path:
## docker
```bash
$ docker compose up
```
- opens port 8080
- exposes `data/db` and `data/avatars` as volumes for data backup and persistence
- exposes `secrets/` as a volume so that the script won't try to perform first time setup again
## manual
1. install:
- OpenResty. instructions for linux can be found [here](https://openresty.org/en/linux-packages.html)
- LuaJIT and Lua 5.1 (usually called `lua5.1` in package managers)
- openssl (-dev)
- sqlite (-dev)
- libsodium (-dev)
- imagemagick (-dev)
- [LuaRocks](https://luarocks.org) (either through the guide's instructions or your package manager, whichever is newer)
2. add luarocks search dirs to path:
```bash
# in .bashrc (or other shell equivalent)
eval "$(luarocks --lua-version 5.1 path)"
```
5. clone repo
6. install the dependencies:
3. clone repo
4. install the lua dependencies:
```bash
$ luarocks --local --lua-version 5.1 build --only-deps
```
7. create a file named `secrets.lua` in the project directory.
use the `secrets.lua.example` file as reference, and generate a cryptographically secure random key, for example, with:
5. run:
```bash
$ openssl rand -hex 32
```
8. run:
```bash
$ start.sh production
$ start.sh production # or 'development' or empty string
```
the script will perform some necessary first time setup (and create a hidden file in the folder to ensure it won't do so again). it will create an administrator account and print the credentials to the console; **this will only happen once**. make sure you save them somewhere. the administrator account is the only one that can promote other users to moderator.
(note the `production` argument. if called with no arguments, `start.sh` will run in a development environment, which uses a separate database.)
(note the `production` argument. if called with no arguments, `start.sh` will run in a development environment, which uses a separate database and shows more debug information.)
this app is made with the assumption that it is being reverse-proxied. as such, you may want to change the port to something other than the default `8080`. you can do that in [`config.lua`]([./config.lua]).

View File

@ -5,7 +5,7 @@ local constants = require("constants")
local util = require("util")
local bcrypt = require("bcrypt")
local auth = require("lib.auth")
local rand = require("openssl.rand")
local models = require("models")
@ -14,7 +14,7 @@ local Sessions = models.Sessions
local Avatars = models.Avatars
local function authenticate_user(user, password)
return bcrypt.verify(password, user.password_hash)
return auth.verify(password, user.password_hash)
end
local function create_session_key()
@ -321,7 +321,7 @@ app:post("user_signup", "/signup", function(self)
local new_user = Users:create({
username = username,
password_hash = bcrypt.digest(password, constants.BCRYPT_ROUNDS),
password_hash = auth.digest(password),
permission = constants.PermissionLevel.GUEST,
})

View File

@ -1,5 +1,5 @@
local config = require("lapis.config")
local secrets = require("secrets")
local secrets = require("secrets.secrets")
config({"development", "production"}, {
port = 8080,
@ -7,7 +7,7 @@ config({"development", "production"}, {
code_cache = "off",
num_workers = "1",
sqlite = {
database = "db.dev.sqlite"
database = "data/db/db.dev.sqlite"
},
secret = "SUPER SECRET",
session_name = "porom_session",
@ -20,7 +20,7 @@ config("production", {
},
secret = secrets.key,
sqlite = {
database = "db.prod.sqlite"
database = "data/db/db.prod.sqlite"
},
session_name = "porom_session_s"
})

View File

@ -1,4 +1,4 @@
local bcrypt = require("bcrypt")
local auth = require("lib.auth")
local models = require("models")
local constants = require("constants")
@ -23,13 +23,14 @@ local function create_admin()
return
end
math.randomseed(os.time())
local password = ""
for _ = 1, 16 do
local randi = math.random(#alphabet)
password = password .. alphabet:sub(randi, randi)
end
local hash = bcrypt.digest(password, constants.BCRYPT_ROUNDS)
local hash = auth.digest(password)
models.Users:create({
username = username,

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -1,13 +0,0 @@
# Generate a random secret key
# export PROD_SECRET_KEY=$(openssl rand -hex 32)
# Start the container
# docker-compose up
version: "3"
services:
porom:
build:
context: .
args:
- PROD_SECRET_KEY=${PROD_SECRET_KEY}
ports:
- "8080:8080"

10
docker-compose.yml Normal file
View File

@ -0,0 +1,10 @@
services:
porom:
build:
context: .
ports:
- "8080:8080"
volumes:
- ./data/static:/app/data/static
- ./data/db:/app/data/db
- ./secrets:/app/secrets

View File

@ -1,36 +0,0 @@
# HOW TO:
#
# Generate a random secret key & build the Docker image
# ```sh
# SECRET_KEY=$(openssl rand -hex 32) docker build --build-arg PROD_SECRET_KEY="$SECRET_KEY" -t porom:latest .
# ```
#
# Then run the container
# ```sh
# docker run -d -p 8080:8080 --name porom porom:latest
# ```
#
FROM openresty/openresty:alpine-fat
COPY ./nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY . /usr/local/openresty/nginx/html
WORKDIR /usr/local/openresty/nginx/html
RUN apk add --no-cache \
make \
git \
make \
gcc \
g++ \
musl-dev \
libffi-dev \
openssl-dev \
sqlite-dev \
imagemagick-dev \
lua5.1 \
lua5.1-dev
RUN eval "$(luarocks --lua-version 5.1 path)"
RUN luarocks --lua-version 5.1 build --only-deps
ARG PROD_SECRET_KEY
RUN echo "return { key = \"${PROD_SECRET_KEY}\",}" > /usr/local/openresty/nginx/html/secrets.lua
EXPOSE 8080
RUN chmod +x /usr/local/openresty/nginx/html/start.sh
ENTRYPOINT ["/usr/local/openresty/nginx/html/start.sh", "production"]

16
lib/auth.lua Normal file
View File

@ -0,0 +1,16 @@
local auth = {}
local ls = require "luasodium"
function auth.digest(password)
return ls.crypto_pwhash_str(
password,
ls.crypto_pwhash_OPSLIMIT_INTERACTIVE,
ls.crypto_pwhash_MEMLIMIT_INTERACTIVE)
end
function auth.verify(password, hash)
return ls.crypto_pwhash_str_verify(hash, password)
end
return auth

View File

@ -26,15 +26,15 @@ http {
}
location /static/ {
alias static/;
alias data/static/;
}
location /favicon.ico {
alias static/favicon.ico;
alias data/static/favicon.ico;
}
location /avatars {
alias static/avatars;
alias data/static/avatars;
expires 1y;
}
}

View File

@ -16,7 +16,7 @@ dependencies = {
"lapis == 1.16.0",
"lsqlite3",
"magick",
"bcrypt",
"luasodium",
"luaossl",
}

View File

@ -1,15 +1,23 @@
#!/bin/bash
set -e
start() {
lapis serve
}
first_launch() {
echo "Setting up for the first time"
touch ".first_launch.$LAPIS_ENVIRONMENT"
lua5.1 schema.lua
mkdir -p secrets
local SECRET
SECRET="$(openssl rand -hex 32)"
echo "return { key = \"${SECRET}\",}" > secrets/secrets.lua
touch "secrets/.touched.$LAPIS_ENVIRONMENT"
mkdir -p data/db
luajit schema.lua
chmod -R a+rw data
lapis migrate
lua5.1 create_default_accounts.lua
luajit create_default_accounts.lua
}
if [[ $# -ne 1 ]]; then
@ -21,7 +29,7 @@ fi
echo "Starting in $LAPIS_ENVIRONMENT"
if ! [ -f ".first_launch.$LAPIS_ENVIRONMENT" ]; then
if ! [ -f "secrets/.touched.$LAPIS_ENVIRONMENT" ]; then
first_launch
fi

View File

@ -1,5 +1,5 @@
<% if infobox then %>
<% render("views.common.infobox", pop_infobox) %>
<% render("views.common.infobox", infobox) %>
<% end %>
<div class="darkbg">
<h1 class="thread-title">Latest posts by <i><%= user.username %></i></h1>