Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Traefik as a depencency - Implement custom proxy #65

Merged
merged 33 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5756dca
add proxy (WIP).
m1k1o Jul 31, 2022
8e93a71
fix proxy for not running rooms.
m1k1o Jul 31, 2022
8fc2027
move lobby to proxy.
m1k1o Jul 31, 2022
7c728eb
internal proxy & admin path prefix.
m1k1o Jul 31, 2022
0da36c0
traefik enable in config.
m1k1o Jul 31, 2022
d5068ae
flexible url if no traefik.
m1k1o Jul 31, 2022
4d2b268
traefik enabled.
m1k1o Jul 31, 2022
2be3852
traefik.network -> instance.network.
m1k1o Jul 31, 2022
9f6c8ef
set traefik config only if enabled.
m1k1o Jul 31, 2022
46ba657
split traefik in dev.
m1k1o Jul 31, 2022
5efafd7
move docker compose to traefik.
m1k1o Jul 31, 2022
2d67345
cleanup traefik readme.
m1k1o Jul 31, 2022
393ad88
Merge branch 'master' into proxy
m1k1o Jul 31, 2022
48f7d94
default path prefix /.
m1k1o Jul 31, 2022
5abcf43
admin path prefix & password.
m1k1o Jul 31, 2022
d779dc6
max connections 0 when using mux.
m1k1o Aug 1, 2022
61b4c0a
proxy store context in labels.
m1k1o Aug 1, 2022
2e6ddf8
proxy fix logging.
m1k1o Aug 1, 2022
11669e0
upgrade to go 1.18.
m1k1o Aug 1, 2022
12d9ebd
replace lobby with proxy.
m1k1o Aug 1, 2022
b906b14
clean path prefixes.
m1k1o Aug 1, 2022
77d8d91
client server for all paths.
m1k1o Aug 1, 2022
9313078
prefix handler is leaf.
m1k1o Aug 3, 2022
ad4e61c
join static, api and proxy in server.
m1k1o Aug 3, 2022
e54d483
remove api config,
m1k1o Aug 3, 2022
1b7f718
revert changes.
m1k1o Aug 3, 2022
9986216
remove admin path prefix.
m1k1o Aug 3, 2022
1796b03
fix traefik dev.
m1k1o Aug 3, 2022
e463866
if not proxying, check for container readiness status.
m1k1o Aug 3, 2022
6a58832
add proxy auth.
m1k1o Aug 3, 2022
2f8bc44
proxy auth add x-forwarded headers.
m1k1o Aug 3, 2022
d86c162
fix x-forwarded headers
m1k1o Aug 3, 2022
39dad00
fix req headers.
m1k1o Aug 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ RUN npm run build
#
# STAGE 2: build executable binary
#
FROM golang:1.17-buster as builder
FROM golang:1.18-buster as builder
WORKDIR /app

COPY . .
Expand All @@ -33,7 +33,7 @@ COPY --from=frontend /src/dist/ /var/www

ENV DOCKER_API_VERSION=1.39
ENV NEKO_ROOMS_BIND=:8080
ENV NEKO_ROOMS_STATIC=/var/www
ENV NEKO_ROOMS_ADMIN_STATIC=/var/www

EXPOSE 8080

Expand Down
2 changes: 2 additions & 0 deletions OpenApi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ components:
max_connections:
type: number
example: 10
description: 0 when using mux
running:
type: boolean
example: true
Expand Down Expand Up @@ -361,6 +362,7 @@ components:
max_connections:
type: number
default: 10
description: 0 when using mux
user_pass:
type: string
example: neko
Expand Down
56 changes: 6 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,70 +16,25 @@ Simple room management system for [n.eko](https://github.com/m1k1o/neko). Self h
<img src="https://github.com/m1k1o/neko-rooms/raw/master/docs/neko.gif" alt="n.eko">
</div>

## Zero-knowledge installation
## Zero-knowledge installation (with HTTPS and Traefik)

If you don't have any clue about docker and stuff but only want to have fun with friends in a shared browser, we got you covered!

- Rent a VPS with public IP and OS Ubuntu.
- Get a domain name pointing to your IP (you can even get some for free).
- Run install script and follow instructions.
- Secure using HTTPs thanks to Let's Encrypt and Traefik.

```bash
wget -O neko-rooms.sh https://raw.githubusercontent.com/m1k1o/neko-rooms/master/install
wget -O neko-rooms.sh https://raw.githubusercontent.com/m1k1o/neko-rooms/master/traefik/install
sudo bash neko-rooms.sh
```

## How to start

You need to have installed `Docker` and `docker-compose`. You need to have a custom domain pointing to your server's IP.
If you want to use Traefik as reverse proxy, visit [installation guide for traefik as reverse proxy](./traefik/).

You can watch installation video provided by *Dr R1ck*:

https://www.youtube.com/watch?v=cCmnw-pq0gA

### Installation guide

You only need `.env.example`, `docker-compose.yml` and `traefik/`.

#### Do I need to use traefik?

- Traefik needs to be used to forward traffic to the rooms. You can put nginx in front of it, but not replace it.
- See example configuration for [nginx](docs/nginx).

You can use `docker-compose.http.yml` that will expose this service to `8080` or any port. Authentication is optional. Start it quickly with `docker-compose -f docker-compose.http.yml up -d`.

### Step 1

Copy `.env.example` to `.env` and customize.

```bash
cp .env.example .env
```

### Step 2

Create `usersfile` with your users:

```bash
touch traefik/usersfile
```

And add as many users as you like:

```bash
echo $(htpasswd -nb user password) >> traefik/usersfile
```

### Step 3 (HTTPS only)

Create `acme.json`

```bash
touch traefik/acme.json
chmod 600 traefik/acme.json
```

Update your email in `traefik/traefik.yml`.
Otherwise modify variables in `docker-compose.yml` and just run `docker-compose up -d`.

### Download images / update

Expand Down Expand Up @@ -116,6 +71,7 @@ For more information visit [docs](./docs).
- [x] add authentication provider for traefik
- [x] allow specifying custom ENV variables
- [x] allow mounting directories for persistent data
- [x] optionally remove Traefik as dependency
- [ ] add upgrade button
- [ ] auto pull images, that do not exist
- [ ] add bearer token to for API
Expand Down
12 changes: 7 additions & 5 deletions client/src/components/RoomInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
:rotate="270"
:size="100"
:width="15"
:value="usesMux ? 100 : ((stats.connections / settings.max_connections) * 100)"
:value="settings.max_connections == 0 ? 100 : ((stats.connections / settings.max_connections) * 100)"
color="blue"
>
{{ stats.connections }} <template v-if="!usesMux">/ {{ settings.max_connections }}</template>
{{ stats.connections }} <template v-if="settings.max_connections > 0">/ {{ settings.max_connections }}</template>
</v-progress-circular>
</div>
</v-col>
Expand Down Expand Up @@ -99,7 +99,10 @@
<span>Invite link for admins</span>
</v-tooltip>
</td></tr>
<tr v-if="!usesMux"><th> Max connections </th><td>{{ settings.max_connections }}</td></tr>
<tr v-if="!usesMux"><th> Max connections </th><td>
<template v-if="settings.max_connections > 0">{{ settings.max_connections }}</template>
<i v-else>not limited because uses mux</i>
</td></tr>
<tr><th> Control protection </th><td>{{ settings.control_protection }}</td></tr>
<tr><th> Implicit Control </th><td>{{ settings.implicit_control }}</td></tr>
</tbody>
Expand Down Expand Up @@ -275,8 +278,7 @@ export default class RoomInfo extends Vue {
}

get usesMux() {
// old rooms might not use mux despite enabled server wide, simple check for that
return this.$store.state.roomsConfig.uses_mux && this.settings?.max_connections == 1
return this.$store.state.roomsConfig.uses_mux
}

get allBrowserExtensions() {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/RoomsCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ export default class RoomsCreate extends Vue {
// eslint-disable-next-line
admin_pass: this.data.admin_pass || randomPassword(),
// eslint-disable-next-line
max_connections: Number(this.data.max_connections), // not needed when uses mux
max_connections: Number(this.data.max_connections), // ignored when uses mux
// eslint-disable-next-line
control_protection: Boolean(this.data.control_protection),
// eslint-disable-next-line
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/RoomsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
</v-tooltip>
</template>
<template v-slot:[`item.max_connections`]="{ item }">
<span v-if="item.max_connections">{{ item.max_connections }}</span>
<i v-else>--not-specified--</i>
<span v-if="item.max_connections > 0">{{ item.max_connections }}</span>
<i v-else>uses mux</i>
</template>
<template v-slot:[`item.status`]="{ item }">
<v-chip :color="item.running ? 'green' : 'red'" dark small> {{ item.status }} </v-chip>
Expand Down
2 changes: 1 addition & 1 deletion client/src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default class Home extends Vue {

get usedConnections() {
// eslint-disable-next-line
return this.$store.state.rooms.reduce((sum: number, { max_connections }: RoomEntry) => sum + (max_connections || 0), 0)
return this.$store.state.rooms.reduce((sum: number, { max_connections }: RoomEntry) => sum + (max_connections || 1/* 0 when using mux */), 0)
}

async LoadRooms() {
Expand Down
1 change: 0 additions & 1 deletion cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ func init() {

configs := []config.Config{
nekoRooms.Service.Configs.Server,
nekoRooms.Service.Configs.API,
nekoRooms.Service.Configs.Room,
}

Expand Down
35 changes: 21 additions & 14 deletions dev/serve
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
#!/bin/sh
cd "$(dirname "$0")"

if [ ! -f "../.env" ]
then
echo "../.env file not found!"
exit 1
if [ -z $APP_PORT ]; then
APP_PORT="8080"
fi

export $(cat ../.env | sed 's/#.*//g' | xargs)
if [ -z $APP_HOST ]; then
for i in $(ifconfig -l 2>/dev/null); do
APP_HOST=$(ipconfig getifaddr $i)
if [ ! -z $APP_HOST ]; then
break
fi
done

if [ -z $APP_HOST ]; then
APP_HOST=$(hostname -i 2>/dev/null)
fi
fi

echo "Using app port: ${APP_PORT}"
echo "Using IP address: ${APP_HOST}"

docker run --rm -it \
--name="neko_rooms_client" \
-v "${PWD}/../client:/app" \
-e "TZ=${TZ}" \
--net="${NEKO_ROOMS_TRAEFIK_NETWORK}" \
-l "traefik.enable=true" \
-l "traefik.http.services.neko-rooms-client-fe.loadbalancer.server.port=8080" \
-l "traefik.http.routers.neko-rooms-client.entrypoints=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-l "traefik.http.routers.neko-rooms-client.rule=Host(\`${NEKO_ROOMS_TRAEFIK_DOMAIN}\`)" \
-p 8081:8080 \
-e "API_PROXY=http://${APP_HOST}:${APP_PORT}" \
--user="$(id -u):$(id -g)" \
--workdir="/app" \
--volume "${PWD}/../client:/app" \
--entrypoint="npm" \
--workdir="/app" \
node:14 run serve;
49 changes: 35 additions & 14 deletions dev/start
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
#!/bin/sh
cd "$(dirname "$0")"

if [ ! -f "../.env" ]
then
echo "../.env file not found!"
exit 1
if [ -z $NEKO_ROOMS_PORT ]; then
NEKO_ROOMS_PORT="8080"
fi

export $(cat ../.env | sed 's/#.*//g' | xargs)
if [ -z $NEKO_ROOMS_EPR ]; then
NEKO_ROOMS_EPR="52090-52099"
fi

if [ -z $NEKO_ROOMS_NAT1TO1 ]; then
for i in $(ifconfig -l 2>/dev/null); do
NEKO_ROOMS_NAT1TO1=$(ipconfig getifaddr $i)
if [ ! -z $NEKO_ROOMS_NAT1TO1 ]; then
break
fi
done

if [ -z $NEKO_ROOMS_NAT1TO1 ]; then
NEKO_ROOMS_NAT1TO1=$(hostname -i 2>/dev/null)
fi
fi

NEKO_ROOMS_INSTANCE_NETWORK="neko-rooms-net"
docker network create --attachable "${NEKO_ROOMS_INSTANCE_NETWORK}";

trap on_exit EXIT

on_exit() {
echo "Removing neko-rooms network"
docker network rm "${NEKO_ROOMS_INSTANCE_NETWORK}";
}

DATA_PATH="./data"
mkdir -p "${DATA_PATH}"
Expand All @@ -17,24 +40,22 @@ mkdir -p "${EXTERNAL_PATH}"

docker run --rm -it \
--name="neko_rooms_server" \
-p "${NEKO_ROOMS_PORT}:8080" \
-v "`realpath ..`:/app" \
-v "`realpath ${DATA_PATH}`:/data" \
-e "TZ=${TZ}" \
-e "NEKO_ROOMS_EPR=${NEKO_ROOMS_EPR}" \
-e "NEKO_ROOMS_MUX=true" \
-e "NEKO_ROOMS_EPR=${NEKO_ROOMS_EPR}" \
-e "NEKO_ROOMS_NAT1TO1=${NEKO_ROOMS_NAT1TO1}" \
-e "NEKO_ROOMS_INSTANCE_URL=http://${NEKO_ROOMS_NAT1TO1}:${NEKO_ROOMS_PORT}/" \
-e "NEKO_ROOMS_INSTANCE_NETWORK=${NEKO_ROOMS_INSTANCE_NETWORK}" \
-e "NEKO_ROOMS_STORAGE_INTERNAL=/data" \
-e "NEKO_ROOMS_STORAGE_EXTERNAL=`realpath ${DATA_PATH}`" \
-e "NEKO_ROOMS_MOUNTS_WHITELIST=`realpath ${EXTERNAL_PATH}`" \
-e "NEKO_ROOMS_TRAEFIK_DOMAIN=${NEKO_ROOMS_TRAEFIK_DOMAIN}" \
-e "NEKO_ROOMS_TRAEFIK_ENTRYPOINT=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-e "NEKO_ROOMS_TRAEFIK_NETWORK=${NEKO_ROOMS_TRAEFIK_NETWORK}" \
-e "NEKO_ROOMS_PATH_PREFIX=/room/" \
-e "NEKO_ROOMS_TRAEFIK_ENABLED=false" \
-e 'DOCKER_API_VERSION=1.39' \
-v "/var/run/docker.sock:/var/run/docker.sock" \
--net="${NEKO_ROOMS_TRAEFIK_NETWORK}" \
-l "traefik.enable=true" \
-l "traefik.http.services.neko-rooms-server-fe.loadbalancer.server.port=8080" \
-l "traefik.http.routers.neko-rooms-server.entrypoints=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-l "traefik.http.routers.neko-rooms-server.rule=Host(\`${NEKO_ROOMS_TRAEFIK_DOMAIN}\`) && PathPrefix(\`/api\`)" \
--net="${NEKO_ROOMS_INSTANCE_NETWORK}" \
--entrypoint="/app/bin/neko_rooms" \
neko_rooms_img serve --bind :8080;
File renamed without changes.
11 changes: 11 additions & 0 deletions dev/traefik/rebuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh
cd "$(dirname "$0")"

set -e

docker run --rm -it \
-v "${PWD}/../../:/app" \
--entrypoint="go" \
neko_rooms_img build -o bin/neko_rooms cmd/neko_rooms/main.go

./start
25 changes: 25 additions & 0 deletions dev/traefik/serve
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh
cd "$(dirname "$0")"

if [ ! -f ".env" ]
then
echo ".env file not found!"
exit 1
fi

export $(cat .env | sed 's/#.*//g' | xargs)

docker run --rm -it \
--name="neko_rooms_client" \
-v "${PWD}/../../client:/app" \
-e "TZ=${TZ}" \
--net="${NEKO_ROOMS_TRAEFIK_NETWORK}" \
-l "traefik.enable=true" \
-l "traefik.http.services.neko-rooms-client-fe.loadbalancer.server.port=8080" \
-l "traefik.http.routers.neko-rooms-client.entrypoints=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-l "traefik.http.routers.neko-rooms-client.rule=Host(\`${NEKO_ROOMS_TRAEFIK_DOMAIN}\`)" \
-l "traefik.http.routers.neko-rooms-client.priority=1" \
--user="$(id -u):$(id -g)" \
--workdir="/app" \
--entrypoint="npm" \
node:14 run serve;
47 changes: 47 additions & 0 deletions dev/traefik/start
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/sh
cd "$(dirname "$0")"

if [ ! -f ".env" ]
then
echo ".env file not found!"
exit 1
fi

export $(cat .env | sed 's/#.*//g' | xargs)

DATA_PATH="../data"
mkdir -p "${DATA_PATH}"

EXTERNAL_PATH="../ext"
mkdir -p "${EXTERNAL_PATH}"

docker run --rm -it \
--name="neko_rooms_server" \
-v "`realpath ../../`:/app" \
-v "`realpath ${DATA_PATH}`:/data" \
-e "TZ=${TZ}" \
-e "NEKO_ROOMS_EPR=${NEKO_ROOMS_EPR}" \
-e "NEKO_ROOMS_MUX=true" \
-e "NEKO_ROOMS_NAT1TO1=${NEKO_ROOMS_NAT1TO1}" \
-e "NEKO_ROOMS_PATH_PREFIX=/room/" \
-e "NEKO_ROOMS_STORAGE_INTERNAL=/data" \
-e "NEKO_ROOMS_STORAGE_EXTERNAL=`realpath ${DATA_PATH}`" \
-e "NEKO_ROOMS_MOUNTS_WHITELIST=`realpath ${EXTERNAL_PATH}`" \
-e "NEKO_ROOMS_TRAEFIK_ENABLED=true" \
-e "NEKO_ROOMS_TRAEFIK_DOMAIN=${NEKO_ROOMS_TRAEFIK_DOMAIN}" \
-e "NEKO_ROOMS_TRAEFIK_ENTRYPOINT=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-e "NEKO_ROOMS_TRAEFIK_NETWORK=${NEKO_ROOMS_TRAEFIK_NETWORK}" \
-e 'DOCKER_API_VERSION=1.39' \
-v "/var/run/docker.sock:/var/run/docker.sock" \
--net="${NEKO_ROOMS_TRAEFIK_NETWORK}" \
-l "traefik.enable=true" \
-l "traefik.http.services.neko-rooms-server-fe.loadbalancer.server.port=8080" \
-l "traefik.http.routers.neko-rooms-server.entrypoints=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-l "traefik.http.routers.neko-rooms-server.rule=Host(\`${NEKO_ROOMS_TRAEFIK_DOMAIN}\`) && PathPrefix(\`/room\`)" \
-l "traefik.http.routers.neko-rooms-server.priority=2" \
-l "traefik.http.routers.neko-rooms-server.service=neko-rooms-server-fe" \
-l "traefik.http.routers.neko-rooms-server-api.entrypoints=${NEKO_ROOMS_TRAEFIK_ENTRYPOINT}" \
-l "traefik.http.routers.neko-rooms-server-api.rule=Host(\`${NEKO_ROOMS_TRAEFIK_DOMAIN}\`) && PathPrefix(\`/api\`)" \
-l "traefik.http.routers.neko-rooms-server-api.service=neko-rooms-server-fe" \
--entrypoint="/app/bin/neko_rooms" \
neko_rooms_img serve --bind :8080;
Loading