diff --git a/.docker/files/base/xorg.conf b/.docker/files/base/xorg.conf
index c803041c..eab523cb 100644
--- a/.docker/files/base/xorg.conf
+++ b/.docker/files/base/xorg.conf
@@ -56,6 +56,8 @@ Section "Monitor"
# 800x600 @ 60.00 Hz (GTF) hsync: 37.32 kHz; pclk: 38.22 MHz
Modeline "800x600_60.00" 38.22 800 832 912 1024 600 601 604 622 -HSync +Vsync
+ # 1920x1080 @ 60.00 Hz (GTF) hsync: 67.08 kHz; pclk: 172.80 MHz
+ Modeline "1920x1080_60.00" 172.80 1920 2040 2248 2576 1080 1081 1084 1118 -HSync +Vsync
# 1920x1080 @ 30.00 Hz (GTF) hsync: 32.97 kHz; pclk: 80.18 MHz
Modeline "1920x1080_30.00" 80.18 1920 1984 2176 2432 1080 1081 1084 1099 -HSync +Vsync
# 1152x648 @ 30.00 Hz (GTF) hsync: 19.80 kHz; pclk: 26.93 MHz
@@ -85,4 +87,4 @@ Section "ServerLayout"
Screen "dummy_screen"
InputDevice "dummy_mouse"
InputDevice "dummy_keyboard"
-EndSection
\ No newline at end of file
+EndSection
diff --git a/.docker/files/chromium/supervisord.conf b/.docker/files/chromium/supervisord.conf
index 90125205..d281d441 100644
--- a/.docker/files/chromium/supervisord.conf
+++ b/.docker/files/chromium/supervisord.conf
@@ -2,11 +2,11 @@
# https://peter.sh/experiments/chromium-command-line-switches/ --no-sandbox
[program:chromium]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
-command=/usr/lib/chromium/chromium --window-position=0,0 --display=%(ENV_DISPLAY)s --start-maximized --bwsi --test-type --force-dark-mode --disable-file-system --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage
+command=/usr/lib/chromium/chromium --window-position=0,0 --display=%(ENV_DISPLAY)s --start-maximized --bwsi --test-type --force-dark-mode --disable-file-system --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage %(ENV_START_URL)s
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/chromium.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
-redirect_stderr=true
\ No newline at end of file
+redirect_stderr=true
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 39f5cfc2..00000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-patreon: nurdism
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 101a0e04..00000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,42 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: "[BUG]"
-labels: ''
-assignees: ''
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Desktop (please complete the following information):**
- - OS: [e.g. iOS]
- - Browser [e.g. chrome, safari]
- - Version [e.g. 22]
-
-**Additional context**
-Add any other context about the problem here.
-
-**Client Log:**
-```
-client log here....
-```
-
-**Server Log:**
-```
-server log here....
-```
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index e0c0168b..00000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: "[FEATURE]"
-labels: ''
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index dc3fcca4..00000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-name: build
-
-on:
- pull_request:
- branches: [ master ]
- paths:
- - 'client/**'
- - 'server/**'
-
-jobs:
- build:
- name: Build
- runs-on: ubuntu-latest
- container: nurdism/neko:dev
- steps:
- - name: Check out code
- uses: actions/checkout@v2
-
- - name: Fetch unshallow
- run: git fetch --prune --tags --unshallow
-
- - name: Get go dependencies and build server
- working-directory: server
- run: |
- go get -v -t -d .
- ./build
-
- - name: Get npm dependencies and build Client
- working-directory: client
- run: |
- npm install
- npm run build
\ No newline at end of file
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
deleted file mode 100644
index 1e5cfd12..00000000
--- a/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: deploy
-
-on:
- push:
- branches: [ master ]
- paths:
- - 'client/**'
- - 'server/**'
-
-jobs:
- deploy:
- name: Deploy
- runs-on: ubuntu-latest
- container: nurdism/neko:dev
- steps:
- - name: Check out code
- uses: actions/checkout@v2
-
- - name: Fetch unshallow
- run: git fetch --prune --tags --unshallow
-
- - name: Get go dependencies and build server
- working-directory: server
- run: |
- go get -v -t -d .
- ./build
-
- - name: Get npm dependencies and build Client
- working-directory: client
- run: |
- npm install
- npm run build
-
- - name: Build the base image
- run: docker build -f ./.docker/files/base/Dockerfile -t nurdism/neko:base .
-
- - name: Build the latest image
- run: docker build -f ./.docker/files/firefox/Dockerfile -t nurdism/neko:latest .
-
- - name: Push the Docker images
- run: |
- echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ secrets.DOCKER_REGISTRY_URL }} -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- docker push nurdism/neko:base
- docker push nurdism/neko:latest
diff --git a/.m1k1o/.env.default b/.m1k1o/.env.default
new file mode 100644
index 00000000..b15828d9
--- /dev/null
+++ b/.m1k1o/.env.default
@@ -0,0 +1,18 @@
+#
+# you can copy this file to .env.local, if you don't want to have it pushed to repository
+#
+
+# this is how will be your images called. you can change it to your fork.
+# only need to do this once. here.
+BUILD_IMAGE="m1k1o/neko"
+
+# this is where your services will be acessible
+CLIENT_PORT=8080
+SERVER_PORT=8081
+
+# on which image you want to test it
+SERVER_TAG="chromium"
+
+# this is needed for WebRTC. specify your local IP address and free UDP port range.
+SERVER_EPR=55000-55009
+SERVER_IP=10.8.0.1
diff --git a/.m1k1o/README.md b/.m1k1o/README.md
new file mode 100644
index 00000000..63e770b7
--- /dev/null
+++ b/.m1k1o/README.md
@@ -0,0 +1,39 @@
+# How to contribute to neko
+
+If you want to contribute, but do not want to install anything on your host system, we got you covered. You only need docker. Technically, it could be done using vs code development in container, but this is more fun:).
+
+You need to copy `.env.development` to `.env` and customize values.
+
+## Step 1: Building server
+
+- `./build` - You can use this command to build your specified `SERVER_TAG` along with base image.
+
+If you want, you can build other tags. `base` tag needs to be build first:
+
+- `./build base`
+- `./build firefox`
+- `./build chromium`
+- etc...
+
+## Step 2: Starting server
+
+- `./start-server` - Starting server image you specified in `.env`.
+- `./start-server -r` - Shortcut for rebuilding server binary and then starting.
+
+If you are changing something in the server code, you do not want to rebuild container each time. You can just rebuild your binary:
+
+- `./rebuild-server` - Rebuild only server binary.
+- `./rebuild-server -f` - Force to rebuild whole Golang environment (you should do this only of you change some dependencies).
+
+## Step 3: Serving client
+
+- `./serve-client` - Serving vue.js client.
+- `./serve-client -i` - Install all dependencies.
+
+## Debug
+
+You can navigate to `CLIENT_PORT` and see live client there. It will be connected to your local server on `SERVER_PORT`.
+
+If you are leaving client as is and not changing it, you don't need to start `./serve-client` and you can access server's GUI directly on `SERVER_PORT`.
+
+Feel free to open new PR.
diff --git a/.m1k1o/base/Dockerfile b/.m1k1o/base/Dockerfile
new file mode 100644
index 00000000..f20f28b6
--- /dev/null
+++ b/.m1k1o/base/Dockerfile
@@ -0,0 +1,125 @@
+#
+# STAGE 1: SERVER
+#
+FROM golang:1.16-buster as server
+WORKDIR /src
+
+#
+# install dependencies
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends git cmake make libx11-dev libxrandr-dev libxtst-dev \
+ libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly; \
+ #
+ # install libclipboard
+ set -eux; \
+ cd /tmp; \
+ git clone https://github.com/jtanx/libclipboard; \
+ cd libclipboard; \
+ cmake .; \
+ make -j4; \
+ make install; \
+ rm -rf /tmp/libclipboard; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# build server
+COPY server/ .
+RUN go get -v -t -d . && go build -o bin/neko cmd/neko/main.go
+
+#
+# STAGE 2: CLIENT
+#
+FROM node:14-buster-slim as client
+WORKDIR /src
+
+#
+# install dependencies
+COPY client/package*.json ./
+RUN npm install
+
+#
+# build client
+COPY client/ .
+RUN npm run build
+
+#
+# STAGE 3: RUNTIME
+#
+FROM debian:buster-slim
+
+#
+# avoid warnings by switching to noninteractive
+ENV DEBIAN_FRONTEND=noninteractive
+
+#
+# set custom user
+ARG USERNAME=neko
+ARG USER_UID=1000
+ARG USER_GID=$USER_UID
+
+#
+# install dependencies
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends wget ca-certificates supervisor; \
+ apt-get install -y --no-install-recommends pulseaudio dbus-x11 xserver-xorg-video-dummy; \
+ apt-get install -y --no-install-recommends libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx5; \
+ #
+ # gst
+ apt-get install -y --no-install-recommends libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
+ gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-pulseaudio; \
+ #
+ # create a non-root user
+ groupadd --gid $USER_GID $USERNAME; \
+ useradd --uid $USER_UID --gid $USERNAME --shell /bin/bash --create-home $USERNAME; \
+ adduser $USERNAME audio; \
+ adduser $USERNAME video; \
+ adduser $USERNAME pulse; \
+ #
+ # setup pulseaudio
+ mkdir -p /home/$USERNAME/.config/pulse/; \
+ echo "default-server=unix:/tmp/pulseaudio.socket" > /home/$USERNAME/.config/pulse/client.conf; \
+ #
+ # workaround for an X11 problem: http://blog.tigerteufel.de/?p=476
+ mkdir /tmp/.X11-unix; \
+ chmod 1777 /tmp/.X11-unix; \
+ chown $USERNAME /tmp/.X11-unix/; \
+ #
+ # make directories for neko
+ mkdir -p /etc/neko /var/www /var/log/neko; \
+ chmod 1777 /var/log/neko; \
+ chown $USERNAME /var/log/neko/; \
+ chown -R $USERNAME:$USERNAME /home/$USERNAME; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy config files
+COPY .m1k1o/base/dbus /usr/bin/dbus
+COPY .m1k1o/base/default.pa /etc/pulse/default.pa
+COPY .m1k1o/base/supervisord.conf /etc/neko/supervisord.conf
+COPY .m1k1o/base/xorg.conf /etc/neko/xorg.conf
+
+#
+# set default envs
+ENV USER=$USERNAME
+ENV DISPLAY=:99.0
+ENV NEKO_PASSWORD=neko
+ENV NEKO_PASSWORD_ADMIN=admin
+ENV NEKO_BIND=:8080
+
+#
+# copy static files from previous stages
+COPY --from=server /src/bin/neko /usr/bin/neko
+COPY --from=client /src/dist/ /var/www
+
+HEALTHCHECK --interval=10s --timeout=5s --retries=8 \
+ CMD wget -O - http://localhost:${NEKO_BIND#*:}/health || exit 1
+
+#
+# run neko
+CMD ["/usr/bin/supervisord", "-c", "/etc/neko/supervisord.conf"]
diff --git a/.m1k1o/base/Dockerfile.arm b/.m1k1o/base/Dockerfile.arm
new file mode 100644
index 00000000..db861687
--- /dev/null
+++ b/.m1k1o/base/Dockerfile.arm
@@ -0,0 +1,136 @@
+#
+# STAGE 1: SERVER
+#
+FROM arm32v7/golang:1.16-buster as server
+WORKDIR /src
+
+#
+# install dependencies
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends git cmake make python2 libx11-dev libxrandr-dev libxtst-dev \
+ libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-omx; \
+ #
+ # install libclipboard
+ set -eux; \
+ cd /tmp; \
+ git clone https://github.com/jtanx/libclipboard; \
+ cd libclipboard; \
+ cmake .; \
+ make -j4; \
+ make install; \
+ rm -rf /tmp/libclipboard; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# build server
+COPY server/ .
+RUN go get -v -t -d . && go build -o bin/neko cmd/neko/main.go
+
+#
+# STAGE 2: CLIENT
+#
+FROM node:14-buster-slim as client
+
+# install dependencies
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends python2 build-essential
+
+WORKDIR /src
+
+#
+# install dependencies
+COPY client/package*.json ./
+RUN npm install
+
+#
+# build client
+COPY client/ .
+RUN npm run build
+
+#
+# STAGE 3: RUNTIME
+#
+FROM balenalib/raspberry-pi-debian:latest
+
+#
+# avoid warnings by switching to noninteractive
+ENV DEBIAN_FRONTEND=noninteractive
+
+#
+# set custom user
+ARG USERNAME=neko
+ARG USER_UID=1000
+ARG USER_GID=$USER_UID
+
+#
+# install dependencies
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends wget ca-certificates supervisor; \
+ apt-get install -y --no-install-recommends pulseaudio dbus-x11 xserver-xorg-video-dummy; \
+ apt-get install -y --no-install-recommends libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx5; \
+ #
+ # gst
+ apt-get install -y --no-install-recommends libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
+ gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-pulseaudio gstreamer1.0-omx; \
+ #
+ # create a non-root user
+ groupadd --gid $USER_GID $USERNAME; \
+ useradd --uid $USER_UID --gid $USERNAME --shell /bin/bash --create-home $USERNAME; \
+ adduser $USERNAME audio; \
+ adduser $USERNAME video; \
+ adduser $USERNAME pulse; \
+ #
+ # setup pulseaudio
+ mkdir -p /home/$USERNAME/.config/pulse/; \
+ echo "default-server=unix:/tmp/pulseaudio.socket" > /home/$USERNAME/.config/pulse/client.conf; \
+ #
+ # workaround for an X11 problem: http://blog.tigerteufel.de/?p=476
+ mkdir /tmp/.X11-unix; \
+ chmod 1777 /tmp/.X11-unix; \
+ chown $USERNAME /tmp/.X11-unix/; \
+ #
+ # make directories for neko
+ mkdir -p /etc/neko /var/www /var/log/neko; \
+ chmod 1777 /var/log/neko; \
+ chown $USERNAME /var/log/neko/; \
+ chown -R $USERNAME:$USERNAME /home/$USERNAME; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy config files
+COPY .m1k1o/base/dbus /usr/bin/dbus
+COPY .m1k1o/base/default.pa /etc/pulse/default.pa
+COPY .m1k1o/base/supervisord.conf /etc/neko/supervisord.conf
+COPY .m1k1o/base/xorg.conf /etc/neko/xorg.conf
+
+#
+# set default envs
+ENV USER=$USERNAME
+ENV DISPLAY=:99.0
+ENV NEKO_PASSWORD=neko
+ENV NEKO_PASSWORD_ADMIN=admin
+ENV NEKO_BIND=:8080
+
+#
+# custom arm values -> video pipeline with GPU encoding
+ENV NEKO_H264=1
+ENV NEKO_VIDEO='ximagesrc display-name=%s use-damage=0 show-pointer=true use-damage=false ! video/x-raw,framerate=30/1 ! videoconvert ! queue ! video/x-raw,framerate=30/1,format=NV12 ! v4l2h264enc extra-controls="controls,h264_profile=0,video_bitrate=1250000;" ! h264parse config-interval=3 ! video/x-h264,profile=baseline,stream-format=byte-stream'
+
+#
+# copy static files from previous stages
+COPY --from=server /src/bin/neko /usr/bin/neko
+COPY --from=client /src/dist/ /var/www
+
+HEALTHCHECK --interval=10s --timeout=5s --retries=8 \
+ CMD wget -O - http://localhost:${NEKO_BIND#*:}/health || exit 1
+
+#
+# run neko
+CMD ["/usr/bin/supervisord", "-c", "/etc/neko/supervisord.conf"]
+
diff --git a/.m1k1o/base/dbus b/.m1k1o/base/dbus
new file mode 100755
index 00000000..bf0d4375
--- /dev/null
+++ b/.m1k1o/base/dbus
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ ! -d /var/run/dbus ]; then
+ mkdir -p /var/run/dbus
+fi
+
+if [ -f /var/run/dbus/pid ]; then
+ rm -f /var/run/dbus/pid
+fi
+
+/usr/bin/dbus-daemon --nofork --print-pid --config-file=/usr/share/dbus-1/system.conf
diff --git a/.m1k1o/base/default.pa b/.m1k1o/base/default.pa
new file mode 100644
index 00000000..b0a26b10
--- /dev/null
+++ b/.m1k1o/base/default.pa
@@ -0,0 +1,7 @@
+#!/usr/bin/pulseaudio -nF
+
+# Allow pulse audio to be accessed via TCP (from localhost only), to allow other users to access the virtual devices
+load-module module-native-protocol-unix socket=/tmp/pulseaudio.socket auth-anonymous=1
+
+### Make sure we always have a sink around, even if it is a null sink.
+load-module module-always-sink
diff --git a/.m1k1o/base/supervisord.conf b/.m1k1o/base/supervisord.conf
new file mode 100644
index 00000000..3df95644
--- /dev/null
+++ b/.m1k1o/base/supervisord.conf
@@ -0,0 +1,53 @@
+[supervisord]
+nodaemon=true
+pidfile=/var/run/supervisord.pid
+logfile=/dev/null
+logfile_maxbytes=0
+loglevel=debug
+
+[include]
+files=/etc/neko/supervisord/*.conf
+
+[program:dbus]
+environment=HOME="/root",USER="root"
+command=/usr/bin/dbus
+autorestart=true
+priority=100
+user=root
+stdout_logfile=/var/log/neko/dbus.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:x-server]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
+command=/usr/bin/X -config /etc/neko/xorg.conf %(ENV_DISPLAY)s
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/xorg.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:pulseaudio]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/pulseaudio --disallow-module-loading -vvvv --disallow-exit --exit-idle-time=-1
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/pulseaudio.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:neko]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/neko serve --static "/var/www"
+autorestart=true
+priority=800
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/neko.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
diff --git a/.m1k1o/base/xorg.conf b/.m1k1o/base/xorg.conf
new file mode 100644
index 00000000..57016ad1
--- /dev/null
+++ b/.m1k1o/base/xorg.conf
@@ -0,0 +1,88 @@
+# This xorg configuration file is meant to be used by xpra
+# to start a dummy X11 server.
+# For details, please see:
+# https://xpra.org/trac/wiki/Xdummy
+
+Section "ServerFlags"
+ Option "DontVTSwitch" "true"
+ Option "AllowMouseOpenFail" "true"
+ Option "PciForceNone" "true"
+ Option "AutoEnableDevices" "false"
+ Option "AutoAddDevices" "false"
+EndSection
+
+Section "InputDevice"
+ Identifier "dummy_mouse"
+ Option "CorePointer" "true"
+ Driver "void"
+EndSection
+
+Section "InputDevice"
+ Identifier "dummy_keyboard"
+ Option "CoreKeyboard" "true"
+ Driver "void"
+EndSection
+
+Section "Device"
+ Identifier "dummy_videocard"
+ Driver "dummy"
+ Option "ConstantDPI" "true"
+ #VideoRam 4096000
+ #VideoRam 256000
+ VideoRam 192000
+EndSection
+
+Section "Monitor"
+ Identifier "dummy_monitor"
+ HorizSync 5.0 - 1000.0
+ VertRefresh 5.0 - 200.0
+ #This can be used to get a specific DPI, but only for the default resolution:
+ #DisplaySize 508 317
+ #NOTE: the highest modes will not work without increasing the VideoRam
+ # for the dummy video card.
+ # https://arachnoid.com/modelines/
+
+ # 1280x720 @ 30.00 Hz (GTF) hsync: 21.99 kHz; pclk: 33.78 MHz
+ Modeline "1280x720_30.00" 33.78 1280 1288 1408 1536 720 721 724 733 -HSync +Vsync
+
+ # 1280x720 @ 60.00 Hz (GTF) hsync: 44.76 kHz; pclk: 74.48 MHz
+ Modeline "1280x720_60.00" 74.48 1280 1336 1472 1664 720 721 724 746 -HSync +Vsync
+ # 1152x648 @ 60.00 Hz (GTF) hsync: 40.26 kHz; pclk: 59.91 MHz
+ Modeline "1152x648_60.00" 59.91 1152 1200 1320 1488 648 649 652 671 -HSync +Vsync
+ # 1024x576 @ 60.00 Hz (GTF) hsync: 35.82 kHz; pclk: 47.00 MHz
+ Modeline "1024x576_60.00" 47.00 1024 1064 1168 1312 576 577 580 597 -HSync +Vsync
+ # 960x720 @ 60.00 Hz (GTF) hsync: 44.76 kHz; pclk: 55.86 MHz
+ Modeline "960x720_60.00" 55.86 960 1008 1104 1248 720 721 724 746 -HSync +Vsync
+ # 800x600 @ 60.00 Hz (GTF) hsync: 37.32 kHz; pclk: 38.22 MHz
+ Modeline "800x600_60.00" 38.22 800 832 912 1024 600 601 604 622 -HSync +Vsync
+
+ # 1920x1080 @ 30.00 Hz (GTF) hsync: 32.97 kHz; pclk: 80.18 MHz
+ Modeline "1920x1080_30.00" 80.18 1920 1984 2176 2432 1080 1081 1084 1099 -HSync +Vsync
+ # 1152x648 @ 30.00 Hz (GTF) hsync: 19.80 kHz; pclk: 26.93 MHz
+ Modeline "1152x648_30.00" 26.93 1152 1144 1256 1360 648 649 652 660 -HSync +Vsync
+ # 1024x576 @ 30.00 Hz (GTF) hsync: 17.61 kHz; pclk: 20.85 MHz
+ Modeline "1024x576_30.00" 20.85 1024 1008 1104 1184 576 577 580 587 -HSync +Vsync
+ # 960x720 @ 30.00 Hz (GTF) hsync: 21.99 kHz; pclk: 25.33 MHz
+ Modeline "960x720_30.00" 25.33 960 960 1056 1152 720 721 724 733 -HSync +Vsync
+ # 800x600 @ 30.00 Hz (GTF) hsync: 18.33 kHz; pclk: 17.01 MHz
+ Modeline "800x600_30.00" 17.01 800 792 864 928 600 601 604 611 -HSync +Vsync
+EndSection
+
+Section "Screen"
+ Identifier "dummy_screen"
+ Device "dummy_videocard"
+ Monitor "dummy_monitor"
+ DefaultDepth 24
+ SubSection "Display"
+ Viewport 0 0
+ Depth 24
+ Modes "1280x720_30.00" "1920x1080_60.00" "1280x720_60.00" "1152x648_60.00" "1024x576_60.00" "960x720_60.00" "800x600_60.00" "1920x1080_30.00" "1152x648_30.00" "1024x576_30.00" "960x720_30.00" "800x600_30.00"
+ EndSubSection
+EndSection
+
+Section "ServerLayout"
+ Identifier "dummy_layout"
+ Screen "dummy_screen"
+ InputDevice "dummy_mouse"
+ InputDevice "dummy_keyboard"
+EndSection
diff --git a/.m1k1o/build b/.m1k1o/build
new file mode 100755
index 00000000..e0848468
--- /dev/null
+++ b/.m1k1o/build
@@ -0,0 +1,75 @@
+#!/bin/sh
+cd "$(dirname "$0")"
+
+BASE="${PWD}/../"
+
+if [ -f ".env.default" ]
+then
+ export $(cat .env.default | sed 's/#.*//g' | xargs)
+fi
+
+if [ -f ".env" ]
+then
+ export $(cat .env | sed 's/#.*//g' | xargs)
+fi
+
+if [ -z "${1}" ] && [ ! -z "${SERVER_TAG}" ]
+then
+ ./build base
+ ./build ${SERVER_TAG}
+ exit 0
+fi
+
+
+build_client() {
+ docker build -t neko-dev-client -f base/Dockerfile --target client "${BASE}"
+ docker run --rm \
+ --user "$(id -u):$(id -g)" \
+ -v "${BASE}client/dist:/tmp/dist" \
+ neko-dev-client sh -c "rm -rf /tmp/dist/*; cp -r /src/dist/* /tmp/dist"
+}
+
+build_server() {
+ docker build -t neko-dev-server -f base/Dockerfile --target server "${BASE}"
+ docker run --rm \
+ --user "$(id -u):$(id -g)" \
+ -v "${BASE}server/bin:/tmp/bin" \
+ neko-dev-server sh -c "rm -rf /tmp/bin/neko; cp /src/bin/neko /tmp/bin"
+}
+
+build() {
+ if [ "$1" = "base" ]
+ then
+ # build base
+ docker build -t "${BUILD_IMAGE}:base" -f base/Dockerfile "${BASE}"
+ else
+ # build image
+ docker build -t "${BUILD_IMAGE}:$1" --build-arg="BASE_IMAGE=${BUILD_IMAGE}:base" -f "$1/Dockerfile" "$1/"
+ fi
+}
+
+build_arm() {
+ if [ "$1" = "base" ]
+ then
+ # build ARM base
+ docker build -t "${BUILD_IMAGE}:arm-base" -f base/Dockerfile.arm "${BASE}"
+ elif [ -f "$1/Dockerfile.arm" ]
+ then
+ # build dedicated ARM image
+ docker build -t "${BUILD_IMAGE}:arm-$1" --build-arg="BASE_IMAGE=${BUILD_IMAGE}:arm-base" -f "$1/Dockerfile.arm" "$1/"
+ else
+ # try to build ARM image with common Dockerfile
+ docker build -t "${BUILD_IMAGE}:arm-$1" --build-arg="BASE_IMAGE=${BUILD_IMAGE}:arm-base" -f "$1/Dockerfile" "$1/"
+ fi
+}
+
+case $1 in
+ client) build_client;;
+ server) build_server;;
+
+ # build arm- images
+ arm-*) build_arm "${1#arm-}";;
+
+ # build images
+ *) build "$1";;
+esac
diff --git a/.m1k1o/chromium/Dockerfile b/.m1k1o/chromium/Dockerfile
new file mode 100644
index 00000000..a6e7d62b
--- /dev/null
+++ b/.m1k1o/chromium/Dockerfile
@@ -0,0 +1,26 @@
+ARG BASE_IMAGE=m1k1o/neko:base
+FROM $BASE_IMAGE
+
+#
+# install neko chromium
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends unzip chromium openbox; \
+ #
+ # install widevine module
+ WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | tail -n 1); \
+ wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/$WIDEVINE_VERSION-linux-x64.zip"; \
+ unzip -p /tmp/widevine.zip libwidevinecdm.so > /usr/lib/chromium/libwidevinecdm.so; \
+ chmod 644 /usr/lib/chromium/libwidevinecdm.so; \
+ rm /tmp/widevine.zip; \
+ #
+ # clean up
+ apt-get --purge autoremove -y unzip; \
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/chromium.conf
+COPY --chown=neko preferences.json /home/neko/.config/chromium/Default/Preferences
+COPY policies.json /etc/chromium/policies/managed/policies.json
+COPY openbox.xml /etc/neko/openbox.xml
diff --git a/.m1k1o/chromium/Dockerfile.arm b/.m1k1o/chromium/Dockerfile.arm
new file mode 100644
index 00000000..208b51a3
--- /dev/null
+++ b/.m1k1o/chromium/Dockerfile.arm
@@ -0,0 +1,19 @@
+ARG BASE_IMAGE=m1k1o/neko:arm-base
+FROM $BASE_IMAGE
+
+#
+# install neko chromium
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends chromium-browser openbox libwidevinecdm0; \
+ ln -s /usr/bin/chromium-browser /usr/bin/chromium; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/chromium.conf
+COPY --chown=neko preferences.json /home/neko/.config/chromium/Default/Preferences
+COPY policies.json /etc/chromium/policies/managed/policies.json
+COPY openbox.xml /etc/neko/openbox.xml
diff --git a/.m1k1o/chromium/openbox.xml b/.m1k1o/chromium/openbox.xml
new file mode 100644
index 00000000..fd1f8941
--- /dev/null
+++ b/.m1k1o/chromium/openbox.xml
@@ -0,0 +1,763 @@
+
+
+
+
+
+
+
+ 10
+ 20
+
+
+
+
+
+ no
+ true
+ yes
+ normal
+
+
+
+
+ yes
+
+ no
+
+ yes
+
+ no
+
+ 200
+
+ no
+
+
+
+
+ Smart
+
+ yes
+
+ Primary
+
+ 1
+
+
+
+
+ Clearlooks
+ NLIMC
+
+ yes
+ yes
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 875
+
+
+
+
+ yes
+ Nonpixel
+
+ Center
+
+
+
+
+ 10
+
+ 10
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+ TopLeft
+
+ 0
+ 0
+ no
+ Above
+
+ Vertical
+
+ no
+ 300
+
+ 300
+
+ Middle
+
+
+
+
+ C-g
+
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scrot -s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yes yes
+
+
+
+
+
+
+
+
+
+
+
+ right
+
+
+
+
+ left
+
+
+
+
+ up
+
+
+
+
+ down
+
+
+
+
+
+
+
+ true
+ Konqueror
+
+ kfmclient openProfile filemanagement
+
+
+
+
+ scrot
+
+
+
+
+ 1
+
+ 500
+
+ 400
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no
+
+
+
+
+
+
+
+
+
+
+ yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+
+
+
+
+
+ left
+
+
+
+
+
+ right
+
+
+
+
+
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vertical
+
+
+ horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+ menu.xml
+ 200
+
+ no
+
+ 100
+
+ 400
+
+ yes
+
+ yes
+
+
+
+
+
+
+
+
diff --git a/.m1k1o/chromium/policies.json b/.m1k1o/chromium/policies.json
new file mode 100644
index 00000000..786c2b15
--- /dev/null
+++ b/.m1k1o/chromium/policies.json
@@ -0,0 +1,38 @@
+{
+ "HomepageLocation": "",
+ "AutoFillEnabled": false,
+ "AutofillAddressEnabled": false,
+ "AutofillCreditCardEnabled": false,
+ "BrowserSignin": 0,
+ "DefaultNotificationsSetting": 2,
+ "DeveloperToolsAvailability": 2,
+ "EditBookmarksEnabled": false,
+ "FullscreenAllowed": true,
+ "IncognitoModeAvailability": 1,
+ "SyncDisabled": true,
+ "AutoplayAllowed": true,
+ "BrowserAddPersonEnabled": false,
+ "BrowserGuestModeEnabled": false,
+ "DefaultPopupsSetting": 2,
+ "DownloadRestrictions": 3,
+ "VideoCaptureAllowed": true,
+ "AllowFileSelectionDialogs": false,
+ "PromptForDownloadLocation": false,
+ "BookmarkBarEnabled": false,
+ "PasswordManagerEnabled": false,
+ "URLBlacklist": [
+ "file://*",
+ "chrome://policy"
+ ],
+ "ExtensionInstallForcelist": [
+ "cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx",
+ "fjoaledfpmneenckfbpdfhkmimnjocfa;https://clients2.google.com/service/update2/crx"
+ ],
+ "ExtensionInstallWhitelist": [
+ "cjpalhdlnbpafiamejdnhcphjbkeiagm",
+ "fjoaledfpmneenckfbpdfhkmimnjocfa"
+ ],
+ "ExtensionInstallBlacklist": [
+ "*"
+ ]
+}
diff --git a/.m1k1o/chromium/preferences.json b/.m1k1o/chromium/preferences.json
new file mode 100644
index 00000000..31cd367a
--- /dev/null
+++ b/.m1k1o/chromium/preferences.json
@@ -0,0 +1,110 @@
+{
+ "homepage": "http://www.google.com",
+ "homepage_is_newtabpage": false,
+ "first_run_tabs": [
+ "https://www.google.com/_/chrome/newtab?ie=UTF-8"
+ ],
+ "custom_links": {
+ "initialized": true,
+ "list": [
+ {
+ "title": "YouTube",
+ "url": "https://www.youtube.com/"
+ },
+ {
+ "title": "Netflix",
+ "url": "https://netflix.com"
+ },
+ {
+ "title": "Hulu",
+ "url": "https://www.hulu.com/"
+ },
+ {
+ "title": "9Anime",
+ "url": "https://9anime.to/"
+ },
+ {
+ "title": "Crunchy Roll",
+ "url": "https://www.crunchyroll.com/"
+ },
+ {
+ "title": "Funimation",
+ "url": "https://www.funimation.com/"
+ },
+ {
+ "title": "Disney+",
+ "url": "https://www.disneyplus.com/"
+ },
+ {
+ "title": "HBO Now",
+ "url": "https://play.hbonow.com/"
+ },
+ {
+ "title": "Amazon Video",
+ "url": "https://www.amazon.com/Amazon-Video/b?node=2858778011"
+ },
+ {
+ "title": "VRV",
+ "url": "https://vrv.co/"
+ },
+ {
+ "title": "Twitch",
+ "url": "https://www.twitch.tv/"
+ },
+ {
+ "title": "Mixer",
+ "url": "https://mixer.com/"
+ }
+ ]
+ },
+ "browser": {
+ "custom_chrome_frame": false,
+ "show_home_button": true,
+ "window_placement": {
+ "maximized": true
+ }
+ },
+ "bookmark_bar": {
+ "show_on_all_tabs": false
+ },
+ "sync_promo": {
+ "show_on_first_run_allowed": false
+ },
+ "distribution": {
+ "import_bookmarks_from_file": "bookmarks.html",
+ "import_bookmarks": true,
+ "import_history": true,
+ "import_home_page": true,
+ "import_search_engine": true,
+ "ping_delay": 60,
+ "do_not_create_desktop_shortcut": true,
+ "do_not_create_quick_launch_shortcut": true,
+ "do_not_create_taskbar_shortcut": true,
+ "do_not_launch_chrome": true,
+ "do_not_register_for_update_launch": true,
+ "make_chrome_default": true,
+ "make_chrome_default_for_user": true,
+ "system_level": false,
+ "verbose_logging": false
+ },
+ "profile": {
+ "avatar_index": 19,
+ "default_content_setting_values": {
+ "clipboard": 2,
+ "cookies": 4,
+ "geolocation": 2,
+ "media_stream_camera": 2,
+ "media_stream_mic": 2,
+ "midi_sysex": 2,
+ "payment_handler": 2,
+ "usb_guard": 2
+ },
+ "name": "neko",
+ "using_default_avatar": false,
+ "using_default_name": false,
+ "using_gaia_avatar": false
+ },
+ "signin": {
+ "allowed": false
+ }
+}
diff --git a/.m1k1o/chromium/supervisord.conf b/.m1k1o/chromium/supervisord.conf
new file mode 100644
index 00000000..a9720173
--- /dev/null
+++ b/.m1k1o/chromium/supervisord.conf
@@ -0,0 +1,21 @@
+[program:chromium]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/chromium --window-position=0,0 --display=%(ENV_DISPLAY)s --user-data-dir=/home/neko/.config/chromium --no-first-run --start-maximized --bwsi --force-dark-mode --disable-file-system --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage
+autorestart=true
+priority=800
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/chromium.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:openbox]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/openbox.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
diff --git a/.m1k1o/firefox/Dockerfile b/.m1k1o/firefox/Dockerfile
new file mode 100644
index 00000000..0f4d7b01
--- /dev/null
+++ b/.m1k1o/firefox/Dockerfile
@@ -0,0 +1,24 @@
+ARG BASE_IMAGE=m1k1o/neko:base
+FROM $BASE_IMAGE
+
+#
+# install firefox-esr
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends openbox firefox-esr; \
+ #
+ # install extensions
+ mkdir -p /usr/lib/firefox-esr/distribution/extensions; \
+ wget -O '/usr/lib/firefox-esr/distribution/extensions/uBlock0@raymondhill.net.xpi' https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi; \
+ wget -O /usr/lib/firefox-esr/distribution/extensions/nordvpnproxy@nordvpn.com.xpi https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/firefox.conf
+COPY neko.js /usr/lib/firefox-esr/mozilla.cfg
+COPY autoconfig.js /usr/lib/firefox-esr/defaults/pref/autoconfig.js
+COPY policies.json /usr/lib/firefox-esr/distribution/policies.json
+COPY openbox.xml /etc/neko/openbox.xml
diff --git a/.m1k1o/firefox/Dockerfile.arm b/.m1k1o/firefox/Dockerfile.arm
new file mode 100644
index 00000000..a307aedc
--- /dev/null
+++ b/.m1k1o/firefox/Dockerfile.arm
@@ -0,0 +1,24 @@
+ARG BASE_IMAGE=m1k1o/neko:arm-base
+FROM $BASE_IMAGE
+
+#
+# install firefox-esr
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends openbox firefox-esr libwidevinecdm0; \
+ #
+ # install extensions
+ mkdir -p /usr/lib/firefox-esr/distribution/extensions; \
+ wget -O '/usr/lib/firefox-esr/distribution/extensions/uBlock0@raymondhill.net.xpi' https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi; \
+ wget -O /usr/lib/firefox-esr/distribution/extensions/nordvpnproxy@nordvpn.com.xpi https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/firefox.conf
+COPY neko.js /usr/lib/firefox-esr/mozilla.cfg
+COPY autoconfig.js /usr/lib/firefox-esr/defaults/pref/autoconfig.js
+COPY policies.json /usr/lib/firefox-esr/distribution/policies.json
+COPY openbox.xml /etc/neko/openbox.xml
diff --git a/.m1k1o/firefox/autoconfig.js b/.m1k1o/firefox/autoconfig.js
new file mode 100644
index 00000000..87d65796
--- /dev/null
+++ b/.m1k1o/firefox/autoconfig.js
@@ -0,0 +1,2 @@
+pref("general.config.obscure_value", 0);
+pref("general.config.filename", "mozilla.cfg");
\ No newline at end of file
diff --git a/.m1k1o/firefox/neko.js b/.m1k1o/firefox/neko.js
new file mode 100644
index 00000000..891d521d
--- /dev/null
+++ b/.m1k1o/firefox/neko.js
@@ -0,0 +1,35 @@
+// firefox config for neko
+lockPref("browser.tabs.closeWindowWithLastTab", false);
+lockPref("app.update.auto", false);
+lockPref("app.update.enabled", false);
+lockPref("app.update.silent", true);
+lockPref("browser.cache.disk.capacity", 1000);
+lockPref("browser.download.useDownloadDir", false);
+lockPref("browser.rights.3.shown", true);
+lockPref("browser.search.update", false);
+lockPref("browser.shell.checkDefaultBrowser", false);
+lockPref("extensions.update.enabled", false);
+lockPref("plugin.default_plugin_disabled", false);
+lockPref("plugin.scan.plid.all", true);
+lockPref("plugins.hide_infobar_for_missing_plugin", true);
+lockPref("profile.allow_automigration", false);
+lockPref("signon.prefillForms", false);
+lockPref("signon.rememberSignons", false);
+lockPref("xpinstall.enabled", false);
+lockPref("xpinstall.whitelist.required", true);
+lockPref("browser.download.manager.retention", 0);
+lockPref("browser.download.folderList", 2);
+lockPref("browser.download.forbid_open_with", true);
+lockPref("browser.safebrowsing.downloads.enabled", false);
+lockPref("browser.safebrowsing.downloads.remote.enabled", false);
+lockPref("browser.helperApps.alwaysAsk.force", false);
+lockPref("browser.helperApps.neverAsk.saveToDisk", "application/zip,application/octet-stream,image/jpeg,application/vnd.ms-outlook,text/html,application/pdf");
+lockPref("browser.helperApps.neverAsk.openFile", "application/zip,application/octet-stream,image/jpeg,application/vnd.ms-outlook,text/html,application/pdf");
+lockPref("browser.newtabpage.activity-stream.default.sites", "https://ipleak.net/,https://www.youtube.com/,https://www.google.com/");
+// dark mode
+lockPref("reader.color_scheme", "dark");
+lockPref("devtools.theme", "dark");
+lockPref("ui.systemUsesDarkTheme", 1);
+lockPref("lightweightThemes.usedThemes","[]");
+lockPref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org");
+lockPref("browser.in-content.dark-mode", true);
diff --git a/.m1k1o/firefox/openbox.xml b/.m1k1o/firefox/openbox.xml
new file mode 100644
index 00000000..0e73a076
--- /dev/null
+++ b/.m1k1o/firefox/openbox.xml
@@ -0,0 +1,763 @@
+
+
+
+
+
+
+
+ 10
+ 20
+
+
+
+
+
+ no
+ true
+ yes
+ normal
+
+
+
+
+ yes
+
+ no
+
+ yes
+
+ no
+
+ 200
+
+ no
+
+
+
+
+ Smart
+
+ yes
+
+ Primary
+
+ 1
+
+
+
+
+ Clearlooks
+ NLIMC
+
+ yes
+ yes
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 875
+
+
+
+
+ yes
+ Nonpixel
+
+ Center
+
+
+
+
+ 10
+
+ 10
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+ TopLeft
+
+ 0
+ 0
+ no
+ Above
+
+ Vertical
+
+ no
+ 300
+
+ 300
+
+ Middle
+
+
+
+
+ C-g
+
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scrot -s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yes yes
+
+
+
+
+
+
+
+
+
+
+
+ right
+
+
+
+
+ left
+
+
+
+
+ up
+
+
+
+
+ down
+
+
+
+
+
+
+
+ true
+ Konqueror
+
+ kfmclient openProfile filemanagement
+
+
+
+
+ scrot
+
+
+
+
+ 1
+
+ 500
+
+ 400
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no
+
+
+
+
+
+
+
+
+
+
+ yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+
+
+
+
+
+ left
+
+
+
+
+
+ right
+
+
+
+
+
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vertical
+
+
+ horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+ menu.xml
+ 200
+
+ no
+
+ 100
+
+ 400
+
+ yes
+
+ yes
+
+
+
+
+
+
+
+
diff --git a/.m1k1o/firefox/policies.json b/.m1k1o/firefox/policies.json
new file mode 100644
index 00000000..8bbb3a1a
--- /dev/null
+++ b/.m1k1o/firefox/policies.json
@@ -0,0 +1,129 @@
+{
+ "policies": {
+ "BlockAboutAddons": false,
+ "BlockAboutConfig": true,
+ "BlockAboutProfiles": true,
+ "BlockAboutSupport": true,
+ "Bookmarks": [
+ {
+ "Title": "IPLeak",
+ "URL": "https://ipleak.net/",
+ "Favicon": "https://ipleak.net/favicon.ico",
+ "Folder": "Pages",
+ "Placement": "toolbar"
+ },
+ {
+ "Title": "YouTube",
+ "URL": "https://www.youtube.com/",
+ "Favicon": "https://www.youtube.com/favicon.ico",
+ "Folder": "Pages",
+ "Placement": "toolbar"
+ },
+ {
+ "Title": "Google",
+ "URL": "https://www.google.com/",
+ "Favicon": "https://www.google.com/favicon.ico",
+ "Folder": "Pages",
+ "Placement": "toolbar"
+ }
+ ],
+ "CaptivePortal": false,
+ "DisableAppUpdate": true,
+ "DisableBuiltinPDFViewer": true,
+ "DisableDeveloperTools": false,
+ "DisableFeedbackCommands": true,
+ "DisableFirefoxAccounts": true,
+ "DisableFirefoxScreenshots": true,
+ "DisableFirefoxStudies": true,
+ "DisableForgetButton": true,
+ "DisableMasterPasswordCreation": true,
+ "DisablePocket": true,
+ "DisablePrivateBrowsing": true,
+ "DisableProfileImport": true,
+ "DisableProfileRefresh": true,
+ "DisableSafeMode": true,
+ "DisableSetDesktopBackground": true,
+ "DisableSystemAddonUpdate": true,
+ "DisableTelemetry": true,
+ "DisplayBookmarksToolbar": false,
+ "DontCheckDefaultBrowser": true,
+ "EnableTrackingProtection": {
+ "Cryptomining": true,
+ "Fingerprinting": true,
+ "Value": true
+ },
+ "ExtensionSettings": {
+ "*": {
+ "installation_mode": "blocked"
+ },
+ "nordvpnproxy@nordvpn.com": {
+ "install_url": "https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi",
+ "installation_mode": "force_installed"
+ },
+ "uBlock0@raymondhill.net": {
+ "install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi",
+ "installation_mode": "force_installed"
+ }
+ },
+ "ExtensionUpdate": false,
+ "FirefoxHome": {
+ "Highlights": false,
+ "Pocket": false,
+ "Search": true,
+ "Snippets": false,
+ "TopSites": true
+ },
+ "FlashPlugin": {},
+ "HardwareAcceleration": false,
+ "Homepage": {
+ "Additional": [],
+ "StartPage": "none"
+ },
+ "NewTabPage": true,
+ "NoDefaultBookmarks": true,
+ "OfferToSaveLogins": false,
+ "OfferToSaveLoginsDefault": false,
+ "OverrideFirstRunPage": "",
+ "OverridePostUpdatePage": "",
+ "PasswordManagerEnabled": false,
+ "Permissions": {
+ "Camera": {
+ "BlockNewRequests": true
+ },
+ "Location": {
+ "BlockNewRequests": true
+ },
+ "Microphone": {
+ "BlockNewRequests": true
+ },
+ "Notifications": {
+ "BlockNewRequests": true
+ }
+ },
+ "Preferences": {
+ "browser.tabs.warnOnClose": false,
+ "browser.urlbar.suggest.bookmark": false,
+ "browser.urlbar.suggest.history": false,
+ "browser.urlbar.suggest.openpage": false,
+ "datareporting.policy.dataSubmissionPolicyBypassNotification": true,
+ "dom.disable_window_flip": true,
+ "dom.disable_window_move_resize": true,
+ "dom.event.contextmenu.enabled": false,
+ "extensions.getAddons.showPane": false,
+ "places.history.enabled": false,
+ "privacy.file_unique_origin": true,
+ "ui.key.menuAccessKeyFocuses": false
+ },
+ "PromptForDownloadLocation": false,
+ "SanitizeOnShutdown": {
+ "Cache": true,
+ "Cookies": true,
+ "Downloads": true,
+ "FormData": true,
+ "History": true,
+ "OfflineApps": true,
+ "Sessions": true,
+ "SiteSettings": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/.m1k1o/firefox/supervisord.conf b/.m1k1o/firefox/supervisord.conf
new file mode 100644
index 00000000..d703a8d2
--- /dev/null
+++ b/.m1k1o/firefox/supervisord.conf
@@ -0,0 +1,21 @@
+[program:firefox-esr]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/lib/firefox-esr/firefox-esr --display=%(ENV_DISPLAY)s -setDefaultBrowser -width 1280 -height 720
+autorestart=true
+priority=800
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/firefox-esr.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:openbox]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/openbox.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
diff --git a/.m1k1o/rebuild-server b/.m1k1o/rebuild-server
new file mode 100755
index 00000000..2726d7d2
--- /dev/null
+++ b/.m1k1o/rebuild-server
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+if [ -f ".env.default" ]
+then
+ export $(cat .env.default | sed 's/#.*//g' | xargs)
+fi
+
+if [ -f ".env" ]
+then
+ export $(cat .env | sed 's/#.*//g' | xargs)
+fi
+
+# use -f to force rebuild
+if [ "$(docker images -q neko_dev_server 2> /dev/null)" == "" ] || [ "$1" == "-f" ]; then
+ docker build -t neko_dev_server -f base/Dockerfile --target server ../
+fi
+
+docker run --rm -it \
+ -v "${PWD}/../server:/src" \
+ --entrypoint="go" \
+ neko_dev_server build -o "bin/neko" "cmd/neko/main.go"
diff --git a/.m1k1o/serve-client b/.m1k1o/serve-client
new file mode 100755
index 00000000..48053f17
--- /dev/null
+++ b/.m1k1o/serve-client
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+if [ -f ".env.default" ]
+then
+ export $(cat .env.default | sed 's/#.*//g' | xargs)
+fi
+
+if [ -f ".env" ]
+then
+ export $(cat .env | sed 's/#.*//g' | xargs)
+fi
+
+# use -i to install
+if [ ! -d "${PWD}/../client/node_modules" ] || [ "$1" == "-i" ]; then
+ docker run --rm -it \
+ -v "${PWD}/../client:/app" \
+ --workdir="/app" \
+ --entrypoint="npm" \
+ node:14-buster-slim install
+fi
+
+docker run --rm -it \
+ -p "${CLIENT_PORT}:8080" \
+ -v "${PWD}/../client:/app" \
+ -e "VUE_APP_SERVER_PORT=${SERVER_PORT}" \
+ --workdir="/app" \
+ --entrypoint="npm" \
+ node:14-buster-slim run serve
+
\ No newline at end of file
diff --git a/.m1k1o/start-server b/.m1k1o/start-server
new file mode 100755
index 00000000..7613dc8f
--- /dev/null
+++ b/.m1k1o/start-server
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+if [ -f ".env.default" ]
+then
+ export $(cat .env.default | sed 's/#.*//g' | xargs)
+fi
+
+if [ -f ".env" ]
+then
+ export $(cat .env | sed 's/#.*//g' | xargs)
+fi
+
+BINARY_PATH="${PWD}/../server/bin/neko"
+
+# use -r to rebuild
+if [ ! -f "${BINARY_PATH}" ] || [ "$1" == "-r" ]; then
+ ./rebuild-server
+fi
+
+docker run --rm -it \
+ --name "neko_dev" \
+ -p "${SERVER_PORT}:8080" \
+ -p "${SERVER_EPR}:${SERVER_EPR}/udp" \
+ -e "NEKO_SCREEN=1920x1080@60" \
+ -e "NEKO_EPR=${SERVER_EPR}" \
+ -e "NEKO_NAT1TO1=${SERVER_IP}" \
+ -e "NEKO_ICELITE=true" \
+ -e "NEKO_MAX_FPS=25" \
+ -v "${BINARY_PATH}:/usr/bin/neko" \
+ --shm-size=2G \
+ --cap-add SYS_ADMIN \
+ ${BUILD_IMAGE}:${SERVER_TAG}
diff --git a/.m1k1o/ungoogled-chromium/Dockerfile b/.m1k1o/ungoogled-chromium/Dockerfile
new file mode 100644
index 00000000..a2c51408
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/Dockerfile
@@ -0,0 +1,40 @@
+ARG BASE_IMAGE=m1k1o/neko:base
+FROM $BASE_IMAGE
+
+ARG SRC_URL="https://github.com/macchrome/linchrome/releases/download/v89.0.4389.114-r843830-portable-ungoogled-Lin64/ungoogled-chromium_89.0.4389.114_1.vaapi_linux.tar.xz"
+
+#
+# install custom chromium build from woolyss with support for hevc/x265
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends wget unzip libatk1.0-0 libatk-bridge2.0-0 libatomic1 \
+ libcups2 libgtk-3-0 libnss3 libpci3 libxcomposite1 libxss1 openbox xz-utils; \
+ wget -O - /tmp/chromium.tar.xz "${SRC_URL}" | tar -xJf- -C /tmp; \
+ mv /tmp/ungoogled-chromium_* /usr/lib/chromium; \
+ #
+ # make required changes for sandbox mode
+ mv /usr/lib/chromium/chrome_sandbox /usr/lib/chromium/chrome-sandbox; \
+ chown root:root /usr/lib/chromium/chrome-sandbox; \
+ chmod 4755 /usr/lib/chromium/chrome-sandbox; \
+ #
+ # install widevine module
+ WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | tail -n 1); \
+ wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/$WIDEVINE_VERSION-linux-x64.zip"; \
+ unzip -p /tmp/widevine.zip libwidevinecdm.so > /usr/lib/chromium/libwidevinecdm.so; \
+ chmod 644 /usr/lib/chromium/libwidevinecdm.so; \
+ rm /tmp/widevine.zip; \
+ #
+ # clean up
+ apt-get --purge autoremove -y xz-utils; \
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/ungoogled-chromium.conf
+COPY preferences.json /usr/lib/chromium/master_preferences
+COPY policies.json /etc/chromium/policies/managed/policies.json
+COPY openbox.xml /etc/neko/openbox.xml
+
+#
+# copy extensions and policy files
+COPY extensions /usr/share/chromium/extensions
diff --git a/.m1k1o/ungoogled-chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.crx b/.m1k1o/ungoogled-chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.crx
new file mode 100644
index 00000000..70d6f176
Binary files /dev/null and b/.m1k1o/ungoogled-chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.crx differ
diff --git a/.m1k1o/ungoogled-chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.json b/.m1k1o/ungoogled-chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.json
new file mode 100644
index 00000000..9a56aa4d
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.json
@@ -0,0 +1,4 @@
+{
+ "external_crx": "/usr/share/chromium/extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm.crx",
+ "external_version": "1.34.0"
+}
diff --git a/.m1k1o/ungoogled-chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.crx b/.m1k1o/ungoogled-chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.crx
new file mode 100644
index 00000000..b4008233
Binary files /dev/null and b/.m1k1o/ungoogled-chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.crx differ
diff --git a/.m1k1o/ungoogled-chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.json b/.m1k1o/ungoogled-chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.json
new file mode 100644
index 00000000..f085274b
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.json
@@ -0,0 +1,4 @@
+{
+ "external_crx": "/usr/share/chromium/extensions/fjoaledfpmneenckfbpdfhkmimnjocfa.crx",
+ "external_version": "2.29.1"
+}
diff --git a/.m1k1o/ungoogled-chromium/openbox.xml b/.m1k1o/ungoogled-chromium/openbox.xml
new file mode 100644
index 00000000..577510c8
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/openbox.xml
@@ -0,0 +1,763 @@
+
+
+
+
+
+
+
+ 10
+ 20
+
+
+
+
+
+ no
+ true
+ yes
+ normal
+
+
+
+
+ yes
+
+ no
+
+ yes
+
+ no
+
+ 200
+
+ no
+
+
+
+
+ Smart
+
+ yes
+
+ Primary
+
+ 1
+
+
+
+
+ Clearlooks
+ NLIMC
+
+ yes
+ yes
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 875
+
+
+
+
+ yes
+ Nonpixel
+
+ Center
+
+
+
+
+ 10
+
+ 10
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+ TopLeft
+
+ 0
+ 0
+ no
+ Above
+
+ Vertical
+
+ no
+ 300
+
+ 300
+
+ Middle
+
+
+
+
+ C-g
+
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scrot -s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yes yes
+
+
+
+
+
+
+
+
+
+
+
+ right
+
+
+
+
+ left
+
+
+
+
+ up
+
+
+
+
+ down
+
+
+
+
+
+
+
+ true
+ Konqueror
+
+ kfmclient openProfile filemanagement
+
+
+
+
+ scrot
+
+
+
+
+ 1
+
+ 500
+
+ 400
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no
+
+
+
+
+
+
+
+
+
+
+ yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+
+
+
+
+
+ left
+
+
+
+
+
+ right
+
+
+
+
+
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vertical
+
+
+ horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+ menu.xml
+ 200
+
+ no
+
+ 100
+
+ 400
+
+ yes
+
+ yes
+
+
+
+
+
+
+
+
diff --git a/.m1k1o/ungoogled-chromium/policies.json b/.m1k1o/ungoogled-chromium/policies.json
new file mode 100644
index 00000000..5c4362cd
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/policies.json
@@ -0,0 +1,34 @@
+{
+ "HomepageLocation": "",
+ "AutoFillEnabled": false,
+ "AutofillAddressEnabled": false,
+ "AutofillCreditCardEnabled": false,
+ "BrowserSignin": 0,
+ "DefaultNotificationsSetting": 2,
+ "DeveloperToolsAvailability": 2,
+ "EditBookmarksEnabled": false,
+ "FullscreenAllowed": true,
+ "IncognitoModeAvailability": 1,
+ "SyncDisabled": true,
+ "AutoplayAllowed": true,
+ "BrowserAddPersonEnabled": false,
+ "BrowserGuestModeEnabled": false,
+ "DefaultPopupsSetting": 2,
+ "DownloadRestrictions": 3,
+ "VideoCaptureAllowed": true,
+ "AllowFileSelectionDialogs": false,
+ "PromptForDownloadLocation": false,
+ "BookmarkBarEnabled": false,
+ "PasswordManagerEnabled": false,
+ "URLBlacklist": [
+ "file://*",
+ "chrome://policy"
+ ],
+ "ExtensionInstallWhitelist": [
+ "cjpalhdlnbpafiamejdnhcphjbkeiagm",
+ "fjoaledfpmneenckfbpdfhkmimnjocfa"
+ ],
+ "ExtensionInstallBlacklist": [
+ "*"
+ ]
+}
diff --git a/.m1k1o/ungoogled-chromium/preferences.json b/.m1k1o/ungoogled-chromium/preferences.json
new file mode 100644
index 00000000..31cd367a
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/preferences.json
@@ -0,0 +1,110 @@
+{
+ "homepage": "http://www.google.com",
+ "homepage_is_newtabpage": false,
+ "first_run_tabs": [
+ "https://www.google.com/_/chrome/newtab?ie=UTF-8"
+ ],
+ "custom_links": {
+ "initialized": true,
+ "list": [
+ {
+ "title": "YouTube",
+ "url": "https://www.youtube.com/"
+ },
+ {
+ "title": "Netflix",
+ "url": "https://netflix.com"
+ },
+ {
+ "title": "Hulu",
+ "url": "https://www.hulu.com/"
+ },
+ {
+ "title": "9Anime",
+ "url": "https://9anime.to/"
+ },
+ {
+ "title": "Crunchy Roll",
+ "url": "https://www.crunchyroll.com/"
+ },
+ {
+ "title": "Funimation",
+ "url": "https://www.funimation.com/"
+ },
+ {
+ "title": "Disney+",
+ "url": "https://www.disneyplus.com/"
+ },
+ {
+ "title": "HBO Now",
+ "url": "https://play.hbonow.com/"
+ },
+ {
+ "title": "Amazon Video",
+ "url": "https://www.amazon.com/Amazon-Video/b?node=2858778011"
+ },
+ {
+ "title": "VRV",
+ "url": "https://vrv.co/"
+ },
+ {
+ "title": "Twitch",
+ "url": "https://www.twitch.tv/"
+ },
+ {
+ "title": "Mixer",
+ "url": "https://mixer.com/"
+ }
+ ]
+ },
+ "browser": {
+ "custom_chrome_frame": false,
+ "show_home_button": true,
+ "window_placement": {
+ "maximized": true
+ }
+ },
+ "bookmark_bar": {
+ "show_on_all_tabs": false
+ },
+ "sync_promo": {
+ "show_on_first_run_allowed": false
+ },
+ "distribution": {
+ "import_bookmarks_from_file": "bookmarks.html",
+ "import_bookmarks": true,
+ "import_history": true,
+ "import_home_page": true,
+ "import_search_engine": true,
+ "ping_delay": 60,
+ "do_not_create_desktop_shortcut": true,
+ "do_not_create_quick_launch_shortcut": true,
+ "do_not_create_taskbar_shortcut": true,
+ "do_not_launch_chrome": true,
+ "do_not_register_for_update_launch": true,
+ "make_chrome_default": true,
+ "make_chrome_default_for_user": true,
+ "system_level": false,
+ "verbose_logging": false
+ },
+ "profile": {
+ "avatar_index": 19,
+ "default_content_setting_values": {
+ "clipboard": 2,
+ "cookies": 4,
+ "geolocation": 2,
+ "media_stream_camera": 2,
+ "media_stream_mic": 2,
+ "midi_sysex": 2,
+ "payment_handler": 2,
+ "usb_guard": 2
+ },
+ "name": "neko",
+ "using_default_avatar": false,
+ "using_default_name": false,
+ "using_gaia_avatar": false
+ },
+ "signin": {
+ "allowed": false
+ }
+}
diff --git a/.m1k1o/ungoogled-chromium/supervisord.conf b/.m1k1o/ungoogled-chromium/supervisord.conf
new file mode 100644
index 00000000..6637b851
--- /dev/null
+++ b/.m1k1o/ungoogled-chromium/supervisord.conf
@@ -0,0 +1,21 @@
+[program:ungoogled-chromium]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/lib/chromium/chrome-wrapper --window-position=0,0 --display=%(ENV_DISPLAY)s --start-maximized --bwsi --test-type --force-dark-mode --disable-file-system --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage
+autorestart=true
+priority=800
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/ungoogled-chromium.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:openbox]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/openbox.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
diff --git a/.m1k1o/vlc/Dockerfile b/.m1k1o/vlc/Dockerfile
new file mode 100644
index 00000000..aea2e1d6
--- /dev/null
+++ b/.m1k1o/vlc/Dockerfile
@@ -0,0 +1,18 @@
+ARG BASE_IMAGE=m1k1o/neko:base
+FROM $BASE_IMAGE
+
+#
+# install vlc
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends openbox vlc; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+ENV VLC_MEDIA="/media"
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/vlc.conf
+COPY openbox.xml /etc/neko/openbox.xml
diff --git a/.m1k1o/vlc/openbox.xml b/.m1k1o/vlc/openbox.xml
new file mode 100644
index 00000000..6b0339c2
--- /dev/null
+++ b/.m1k1o/vlc/openbox.xml
@@ -0,0 +1,763 @@
+
+
+
+
+
+
+
+ 10
+ 20
+
+
+
+
+
+ no
+ true
+ yes
+ normal
+
+
+
+
+ yes
+
+ no
+
+ yes
+
+ no
+
+ 200
+
+ no
+
+
+
+
+ Smart
+
+ yes
+
+ Primary
+
+ 1
+
+
+
+
+ Clearlooks
+ NLIMC
+
+ yes
+ yes
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 875
+
+
+
+
+ yes
+ Nonpixel
+
+ Center
+
+
+
+
+ 10
+
+ 10
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+ TopLeft
+
+ 0
+ 0
+ no
+ Above
+
+ Vertical
+
+ no
+ 300
+
+ 300
+
+ Middle
+
+
+
+
+ C-g
+
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scrot -s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yes yes
+
+
+
+
+
+
+
+
+
+
+
+ right
+
+
+
+
+ left
+
+
+
+
+ up
+
+
+
+
+ down
+
+
+
+
+
+
+
+ true
+ Konqueror
+
+ kfmclient openProfile filemanagement
+
+
+
+
+ scrot
+
+
+
+
+ 1
+
+ 500
+
+ 400
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no
+
+
+
+
+
+
+
+
+
+
+ yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+
+
+
+
+
+ left
+
+
+
+
+
+ right
+
+
+
+
+
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vertical
+
+
+ horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+ menu.xml
+ 200
+
+ no
+
+ 100
+
+ 400
+
+ yes
+
+ yes
+
+
+
+
+
+
+
+
diff --git a/.m1k1o/vlc/supervisord.conf b/.m1k1o/vlc/supervisord.conf
new file mode 100644
index 00000000..f219e950
--- /dev/null
+++ b/.m1k1o/vlc/supervisord.conf
@@ -0,0 +1,21 @@
+[program:vlc]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/vlc --x11-display=%(ENV_DISPLAY)s --no-qt-privacy-ask %(ENV_VLC_MEDIA)s
+autorestart=true
+priority=800
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/vlc.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:openbox]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/openbox.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
diff --git a/.m1k1o/vncviewer/Dockerfile b/.m1k1o/vncviewer/Dockerfile
new file mode 100644
index 00000000..e6303872
--- /dev/null
+++ b/.m1k1o/vncviewer/Dockerfile
@@ -0,0 +1,18 @@
+ARG BASE_IMAGE=m1k1o/neko:base
+FROM $BASE_IMAGE
+
+#
+# install vncviewer
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends openbox xtightvncviewer; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+ENV NEKO_VNC_URL=""
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/vncviewer.conf
+COPY openbox.xml /etc/neko/openbox.xml
diff --git a/.m1k1o/vncviewer/openbox.xml b/.m1k1o/vncviewer/openbox.xml
new file mode 100644
index 00000000..7b5f0ecf
--- /dev/null
+++ b/.m1k1o/vncviewer/openbox.xml
@@ -0,0 +1,763 @@
+
+
+
+
+
+
+
+ 10
+ 20
+
+
+
+
+
+ no
+ true
+ yes
+ normal
+
+
+
+
+ yes
+
+ no
+
+ yes
+
+ no
+
+ 200
+
+ no
+
+
+
+
+ Smart
+
+ yes
+
+ Primary
+
+ 1
+
+
+
+
+ Clearlooks
+ NLIMC
+
+ yes
+ yes
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 8
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ normal
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+ sans
+ 9
+
+ bold
+
+ normal
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+ 875
+
+
+
+
+ yes
+ Nonpixel
+
+ Center
+
+
+
+
+ 10
+
+ 10
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+ TopLeft
+
+ 0
+ 0
+ no
+ Above
+
+ Vertical
+
+ no
+ 300
+
+ 300
+
+ Middle
+
+
+
+
+ C-g
+
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ left no
+
+
+ right no
+
+
+ up no
+
+
+ down no
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scrot -s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yes yes
+
+
+
+
+
+
+
+
+
+
+
+ right
+
+
+
+
+ left
+
+
+
+
+ up
+
+
+
+
+ down
+
+
+
+
+
+
+
+ true
+ Konqueror
+
+ kfmclient openProfile filemanagement
+
+
+
+
+ scrot
+
+
+
+
+ 1
+
+ 500
+
+ 400
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no
+
+
+
+
+
+
+
+
+
+
+ yes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ top
+
+
+
+
+
+ left
+
+
+
+
+
+ right
+
+
+
+
+
+ bottom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vertical
+
+
+ horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ previous
+
+
+ next
+
+
+ previous
+
+
+ next
+
+
+
+
+
+
+
+
+
+
+ menu.xml
+ 200
+
+ no
+
+ 100
+
+ 400
+
+ yes
+
+ yes
+
+
+
+
+
+
+
+
diff --git a/.m1k1o/vncviewer/supervisord.conf b/.m1k1o/vncviewer/supervisord.conf
new file mode 100644
index 00000000..c3ebdd84
--- /dev/null
+++ b/.m1k1o/vncviewer/supervisord.conf
@@ -0,0 +1,21 @@
+[program:vncviewer]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/vncviewer -autopass -x11cursor -nojpeg -quality 9 -compresslevel 9 %(ENV_NEKO_VNC_URL)s
+autorestart=true
+priority=800
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/vncviewer.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
+[program:openbox]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
+autorestart=true
+priority=300
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/openbox.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
diff --git a/.m1k1o/xfce/Dockerfile b/.m1k1o/xfce/Dockerfile
new file mode 100644
index 00000000..b1aa6a7d
--- /dev/null
+++ b/.m1k1o/xfce/Dockerfile
@@ -0,0 +1,20 @@
+ARG BASE_IMAGE=m1k1o/neko:base
+FROM $BASE_IMAGE
+
+#
+# install xfce
+RUN set -eux; apt-get update; \
+ apt-get install -y --no-install-recommends xfce4 xfce4-terminal sudo; \
+ #
+ # add user to sudoers
+ usermod -aG sudo neko; \
+ echo "neko:neko" | chpasswd; \
+ echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers; \
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy configuation files
+COPY supervisord.conf /etc/neko/supervisord/xfce.conf
+
diff --git a/.m1k1o/xfce/supervisord.conf b/.m1k1o/xfce/supervisord.conf
new file mode 100644
index 00000000..c7664aa4
--- /dev/null
+++ b/.m1k1o/xfce/supervisord.conf
@@ -0,0 +1,11 @@
+[program:xfce]
+environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
+command=/usr/bin/startxfce4
+autorestart=true
+priority=500
+user=%(ENV_USER)s
+stdout_logfile=/var/log/neko/xfce.log
+stdout_logfile_maxbytes=100MB
+stdout_logfile_backups=10
+redirect_stderr=true
+
diff --git a/README.md b/README.md
index 4b305375..4244834d 100644
--- a/README.md
+++ b/README.md
@@ -1,50 +1,283 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# n.eko (m1k1o fork)
+This app uses Web RTC to stream a desktop inside of a docker container. This is fork of https://github.com/nurdism/neko.
+For n.eko room management software visit https://github.com/m1k1o/neko-rooms.
-# n.eko
- This app uses Web RTC to stream a desktop inside of a docker container, I made this because [rabb.it](https://en.wikipedia.org/wiki/Rabb.it) went under and my internet can't handle streaming and discord keeps crashing when my friend attempts to. I just want to watch anime with my friends ლ(ಠ益ಠლ) so I started digging throughout the internet and found a few *kinda* clones, but none of them had the virtual browser, then I found [Turtus](https://github.com/Khauri/Turtus) and I was able to figure out the rest. This is by no means a fully featured clone of rabbit, it hs only *one* room. It's stateless, so no saved user names or passwords.
+## Differences to original repository.
-## Features
- * Text Chat (With basic markdown support, discord flavor)
- * Admin users (Kick, Ban & Force Give/Release Controls)
- * Clipboard synchronization (on [supported browsers](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText))
- * Emote overlay
- * Ignore user (chat and emotes)
- * Persistent settings
+### New Features
+- Clipboard button with text area - for browsers, that don't support clipboard syncing (FireFox, what a shame...) or for HTTP.
+- Keyboard modifier state synchronization (Num Lock, Caps Lock, Scroll Lock) for each hosting.
+- Added chromium ungoogled (with h265 support) an kept up to date (by @whalehub).
+- Added Picture in Picture button (only for watching screen, controlling not possible).
+- Added RTMP broadcast. Enables broadcasting neko screen to local RTMP server, YouTube or Twitch.
+- Stereo sound (works properly only in Firefox host).
+- Added limited support for some mobile browsers with `playsinline` attribute.
+- Added `VIDEO_BITRATE` and `AUDIO_BITRATE` in kbit/s to control stream quality (in collaboration with @mbattista).
+- Added `MAX_FPS`, where you can specify max WebRTC frame rate. When set to `0`, frame rate won't be capped and you can enjoy your real `60fps` experience. Originally, it was constant at `25fps`.
+- Invite links. You can invite people and they don't need to enter passwords by themselves (and get confused about user accounts that do not exits). You can put your password in URL using `?pwd=` and it will be automatically used when logging in.
+- Added `/stats?pwd=` endpoint to get total active connections, host and members.
+- Added `m1k1o/neko:vlc` tag, use VLC to watch local files together (by @mbattista).
+- Added `m1k1o/neko:xfce` tag, as an non video related showcase (by @mbattista).
+- Added ARM-based images, for Raspberry Pi support (by @mbattista).
+- Added simple language picker.
-## Why n.eko?
-I like cats 🐱 (`Neko` is the Japanese word for cat), I'm a weeb/nerd
+### Bugs
+- Fixed minor gst pipeline bug.
+- Locked screen only for users, admins can still join.
+- Fixed h264 pipelines bugs (by @mbattista).
+- Fixed sessions manager thread safety by adding mutexes (caused panic in rare edge cases).
+- Now when user gets kicked, he won't join as a ghost user again but will be logged out.
+- **iOS compatibility!** Fixed really strange CSS bug, which prevented iOS from loading the video.
+- Proper disconnect only once with unsubscribing events. When webrtc fails, user won't be logged in without username again.
-***But why the cat butt?*** Because cats are *assholes*, but you love them anyways.
+### Misc
+- Custom docker workflow.
+- Based on debian buster instead of stretch.
+- Versions bumped: Go 16, Node.js 14 (by @mbattista).
+- Custom avatars without any 3rd party depenency.
+- Ignore duplicate notify bars.
+- No pointer events for notify bars.
+- Disable debug mode by default.
+- Remove HTML tags from user name.
+- Upgraded `pion/webrtc` to v3 (by @mbattista).
+- Added `requestFullscreen` compatibility for older browsers.
+- Fixed small lags in video and improved video UX (by @mbattista).
+- Added `m1k1o/neko:vncviewer` tag, use `NEKO_VNC_URL` to specify VNC target and use n.eko as a bridge.
+- Abiltiy to include neko as a component in another Vue.Js project (by @gbrian).
+- Added HEALTHCHECK to Dockerfile.
+- Arguments in broadcast pipeline are optional, not positional and can be repeated `{url} {device} {display}`.
-## Documentation
+### Roadmap & TODOs
+- Catch errors from gst pipeline, tell user if broadcast failed.
-* [Getting Started](https://n.eko.moe/#/getting-started)
- * [Quick Start](https://n.eko.moe/#/quick-start)
- * [Configuration](https://n.eko.moe/#/configuration)
-* [Development](https://n.eko.moe/#/development)
- * [Client](https://n.eko.moe/#/client)
- * [Server](https://n.eko.moe/#/server)
- * [Docker](https://n.eko.moe/#/docker)
- * [Non Goals](https://n.eko.moe/#/non-goals)
- * [Contributing](https://n.eko.moe/#/contributing)
- * [Change logs](https://n.eko.moe/#/change-logs/)
-* [Technologies](https://n.eko.moe/#/technologies)
-* [Glossary](https://n.eko.moe/#/glossary)
+# Getting started & FAQ
+
+Use following docker images:
+- `m1k1o/neko:latest` - for Firefox.
+- `m1k1o/neko:chromium` - for Chromium (needs `--cap-add=SYS_ADMIN`).
+- `m1k1o/neko:ungoogled-chromium` - for [Ungoogled Chromium](https://github.com/Eloston/ungoogled-chromium) (needs `--cap-add=SYS_ADMIN`) (by @whalehub).
+- `m1k1o/neko:vncviewer` - for simple VNC viewer (specify `NEKO_VNC_URL` to your VNC target).
+- `m1k1o/neko:vlc` - for VLC Video player (needs volume mounted to `/media` with local video files, or setting `VLC_MEDIA=/media` path).
+- `m1k1o/neko:xfce` - for an shared desktop / installing shared software.
+- `m1k1o/neko:base` - for custom base.
+
+For ARM-based devices (like Raspberry Pi, with GPU hardware acceleration):
+- `m1k1o/neko:arm-firefox` - for Firefox.
+- `m1k1o/neko:arm-chromium` - for Chromium.
+- `m1k1o/neko:arm-base` - for custom arm based.
+
+Networking:
+- If you want to use n.eko in **external** network, you can omit `NEKO_NAT1TO1`. It will automatically get your Public IP.
+- If you want to use n.eko in **internal** network, set `NEKO_NAT1TO1` to your local IP address (e.g. `NEKO_NAT1TO1: 192.168.1.20`)-
+
+Why so many ports?
+- WebRTC needs UDP ports for each channel it creates towards users.
+- Every user will need 2 UDP ports (for getting audio/video and sending mouse positions).
+- You can freely limit number of UDP ports. But you can't map them to diferent ports.
+ - This **WONT** work: `32000-32100:52000-52100/udp`
+- You can change API port (8080).
+ - This **WILL** work: `3000:8080`
+
+Behind reverse proxy?
+- Nginx configuration: https://github.com/nurdism/neko/issues/111#issuecomment-742656957
+- Apache configuration: https://github.com/nurdism/neko/blob/cad98a62a5bd7f1daf2c11980631bb14ba81a1f6/docs/apache-proxypass-config.md#example-apache-config
+- Traefik configuration: https://github.com/m1k1o/neko-vpn/blob/a1b934515dcf597992a515d61d307c2450a11002/docker-compose.yml#L38-L43
+
+Want to use VPN for your neko browsing?
+- Check this out: https://github.com/m1k1o/neko-vpn
+
+Accounts:
+- There are no accounts, display name (a.k.a. username) can be freely chosen. Only paword needs to match. Depeding on which password matches, visitor gets its privilege:
+ - Anyone, who enters with `NEKO_PASSWORD` will be **user**.
+ - Anyone, who enters with `NEKO_PASSWORD_ADMIN` will be **admin**.
+
+Screen size
+- Only admins can change screen size.
+- You can set default screen size, but this size **MUST** be one from list, that your server supports.
+- You will get this list in frontend, where you can choose from.
+
+## Firefox
+
+```yaml
+version: "3.4"
+services:
+ neko:
+ image: "m1k1o/neko:latest"
+ restart: "unless-stopped"
+ shm_size: "2gb"
+ ports:
+ - "8080:8080"
+ - "52000-52100:52000-52100/udp"
+ environment:
+ NEKO_SCREEN: '1920x1080@30'
+ NEKO_PASSWORD: neko
+ NEKO_PASSWORD_ADMIN: admin
+ NEKO_EPR: 52000-52100
+ NEKO_NAT1TO1:
+```
+
+## Chromium
+
+```yaml
+version: "3.4"
+services:
+ neko:
+ image: "m1k1o/neko:chromium"
+ restart: "unless-stopped"
+ shm_size: "2gb"
+ ports:
+ - "8080:8080"
+ - "52000-52100:52000-52100/udp"
+ cap_add:
+ - SYS_ADMIN
+ environment:
+ NEKO_SCREEN: '1920x1080@30'
+ NEKO_PASSWORD: neko
+ NEKO_PASSWORD_ADMIN: admin
+ NEKO_EPR: 52000-52100
+ NEKO_NAT1TO1:
+```
+
+## VLC
+
+```yaml
+version: "3.4"
+services:
+ neko:
+ image: "m1k1o/neko:vlc"
+ restart: "unless-stopped"
+ shm_size: "2gb"
+ volumes:
+ - ":/video"
+ ports:
+ - "8080:8080"
+ - "52000-52100:52000-52100/udp"
+ cap_add:
+ - SYS_ADMIN
+ environment:
+ NEKO_SCREEN: '1920x1080@30'
+ NEKO_PASSWORD: neko
+ NEKO_PASSWORD_ADMIN: admin
+ NEKO_EPR: 52000-52100
+ NEKO_NAT1TO1:
+```
+
+## Raspberry Pi
+
+Note! Since this pipeline is using H264, that enables GPU HW acceleration for Raspberry Pi, you are only able to connect from browsers supporting H264 for WebRTC. At the time of implementing, [Firefox does not support this](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#supported-foot-1).
+
+```yaml
+version: "3.4"
+services:
+ neko:
+ image: "m1k1o/neko:arm-chromium"
+ restart: "unless-stopped"
+ # increase on rpi's with more then 1gb ram.
+ shm_size: "520mb"
+ ports:
+ - "8088:8080"
+ - "52000-52100:52000-52100/udp"
+ # this is important since we need a GPU for hardware acceleration alternatively mount the devices into the docker.
+ privileged: true
+ environment:
+ NEKO_SCREEN: '1280x720@30'
+ NEKO_PASSWORD: 'neko'
+ NEKO_PASSWORD_ADMIN: 'admin'
+ NEKO_EPR: 52000-52100
+ # optional: change target bitrate and framerate on this parameter.
+ NEKO_VIDEO: |
+ ximagesrc display-name=%s use-damage=0 show-pointer=true use-damage=false
+ ! video/x-raw,framerate=30/1
+ ! videoconvert
+ ! queue
+ ! video/x-raw,framerate=30/1,format=NV12
+ ! v4l2h264enc extra-controls="controls,h264_profile=0,video_bitrate=1250000;"
+ ! h264parse config-interval=3
+ ! video/x-h264,profile=baseline,stream-format=byte-stream
+```
+
+## Mobile support
+
+Neko is now working on iOS and Android! Also, the UI screens have been fixed for small screens.
+
+![mobile-screens](https://i.imgur.com/K9gfscU.png)
+
+## Docker-Compose Enviroment Options
+
+```code
+NEKO_SCREEN:
+ - Resolution after startup. Only Admins can change this later.
+ - e.g. '1920x1080@30'
+NEKO_PASSWORD:
+ - Password for the user login
+ - e.g. 'user_password'
+NEKO_PASSWORD_ADMIN
+ - Password for the admin login
+ - e.g. 'admin_password'
+NEKO_EPR:
+ - For WebRTC needed range of ports
+ - e.g. 52000-52100
+NEKO_VP8:
+ - If vp8 should be used as video encoder for the stream (default encoder)
+ - e.g. 'true'
+NEKO_VP9:
+ - If vp9 should be used as video encoder for the stream (Parameter not optimized yet)
+ - e.g. 'false'
+NEKO_H264:
+ - If h264 should be used as video encoder for the stream (second best option)
+ - e.g. 'false'
+NEKO_VIDEO_BITRATE:
+ - Bitrate of the video stream in kb/s
+ - e.g. 3500
+NEKO_VIDEO:
+ - Makes it possible to create custom gstreamer pipelines. With this you could find the best quality for your CPU
+ - Installed are gstreamer1.0-plugins-base / gstreamer1.0-plugins-good / gstreamer1.0-plugins-bad / gstreamer1.0-plugins-ugly
+ - e.g. ' ximagesrc display-name=%s show-pointer=true use-damage=false ! video/x-raw,framerate=30/1 ! videoconvert ! queue ! video/x-raw,format=NV12 ! x264enc threads=4 bitrate=3500 key-int-max=60 vbv-buf-capacity=4000 byte-stream=true tune=zerolatency speed-preset=veryfast ! video/x-h264,stream-format=byte-stream '
+NEKO_MAX_FPS:
+ - The resulting stream frames per seconds should be capped (0 for uncapped)
+ - e.g. 0
+NEKO_OPUS:
+ - If opus should be used as audio encoder for the stream (default encoder)
+ - e.g. 'true'
+NEKO_G722:
+ - If g722 should be used as audio encoder for the stream
+ - e.g. 'false'
+NEKO_PCMU:
+ - If pcmu should be used as audio encoder for the stream
+ - e.g. 'false'
+NEKO_PCMA:
+ - If pcma should be used as audio encoder for the stream
+ - e.g. 'false'
+NEKO_AUDIO_BITRATE:
+ - Bitrate of the audio stream in kb/s
+ - e.g. 196
+NEKO_CERT:
+ - Path to the SSL-Certificate
+ - e.g. '/certs/cert.pem'
+NEKO_KEY:
+ - Path to the SSL-Certificate private key
+ - e.g. '/certs/key.pem'
+
+```
+
+# How to contribute?
+
+Navigate to `.m1k1o/README.md` for further information.
diff --git a/client/package.json b/client/package.json
index 6497810a..0157458d 100644
--- a/client/package.json
+++ b/client/package.json
@@ -15,53 +15,55 @@
"scripts": {
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build",
+ "build:lib": "vue-cli-service build --target lib --name neko-lib 'src/lib.ts'",
"build:emoji": "ts-node --files --project tools/tsconfig.json tools/emoji.ts",
"lint": "vue-cli-service lint"
},
"dependencies": {
- "@fortawesome/fontawesome-free": "^5.13.0",
- "animejs": "^3.1.0",
- "axios": "^0.19.1",
- "date-fns": "^2.11.1",
- "emoji-datasource": "^5.0.1",
- "emojilib": "^2.4.0",
- "eventemitter3": "^4.0.0",
+ "@fortawesome/fontawesome-free": "^5.14.0",
+ "animejs": "^3.2.0",
+ "axios": "^0.21.1",
+ "date-fns": "^2.16.1",
+ "emoji-datasource": "^6.0.1",
+ "emojilib": "^3.0.1",
+ "eventemitter3": "^4.0.7",
"resize-observer-polyfill": "^1.5.1",
"simple-markdown": "^0.7.2",
- "sweetalert2": "^9.10.9",
- "typed-vuex": "^0.1.17",
+ "sweetalert2": "^10.15.7",
+ "typed-vuex": "^0.1.21",
"v-tooltip": "^2.0.3",
- "vue": "^2.6.10",
- "vue-class-component": "^7.2.3",
+ "vue": "^2.6.12",
+ "vue-class-component": "^7.2.6",
"vue-clickaway": "^2.2.2",
- "vue-context": "^5.1.0",
- "vue-i18n": "^8.16.0",
+ "vue-context": "^5.2.0",
+ "vue-i18n": "^8.21.1",
"vue-notification": "^1.3.20",
- "vue-property-decorator": "^8.4.1",
- "vuex": "^3.1.3"
+ "vue-property-decorator": "^9.1.2",
+ "vuex": "^3.5.1"
},
"devDependencies": {
- "@types/animejs": "^3.1.0",
- "@types/node": "^13.7.0",
+ "@types/animejs": "^3.1.2",
+ "@types/node": "^14.14.37",
"@types/vue": "^2.0.0",
"@types/vue-clickaway": "^2.2.0",
- "@typescript-eslint/eslint-plugin": "^2.26.0",
- "@typescript-eslint/parser": "^2.26.0",
- "@vue/cli-plugin-babel": "^4.1.0",
- "@vue/cli-plugin-eslint": "^4.1.0",
- "@vue/cli-plugin-typescript": "^4.1.0",
- "@vue/cli-plugin-vuex": "^4.1.0",
- "@vue/cli-service": "^4.1.0",
+ "@typescript-eslint/eslint-plugin": "^4.19.0",
+ "@typescript-eslint/parser": "^4.19.0",
+ "@vue/cli-plugin-babel": "^4.5.6",
+ "@vue/cli-plugin-eslint": "^4.5.6",
+ "@vue/cli-plugin-typescript": "^4.5.6",
+ "@vue/cli-plugin-vuex": "^4.5.6",
+ "@vue/cli-service": "^4.5.12",
"@vue/eslint-config-prettier": "^6.0.0",
- "@vue/eslint-config-typescript": "^5.0.2",
+ "@vue/eslint-config-typescript": "^7.0.0",
+ "core-js": "^3.9.1",
"eslint": "^6.8.0",
- "eslint-plugin-prettier": "^3.1.1",
- "eslint-plugin-vue": "^6.2.2",
- "node-sass": "^4.12.0",
- "prettier": "^2.0.2",
- "sass-loader": "^8.0.0",
- "ts-node": "^8.6.2",
- "typescript": "^3.8.3",
- "vue-template-compiler": "^2.6.10"
+ "eslint-plugin-prettier": "^3.1.4",
+ "eslint-plugin-vue": "^7.8.0",
+ "node-sass": "^5.0.0",
+ "prettier": "^2.1.2",
+ "sass-loader": "^10.1.1",
+ "ts-node": "^9.1.1",
+ "typescript": "^4.2.3",
+ "vue-template-compiler": "^2.6.12"
}
}
diff --git a/client/public/index.html b/client/public/index.html
index c4105895..fd6c2703 100644
--- a/client/public/index.html
+++ b/client/public/index.html
@@ -5,13 +5,14 @@
n.eko
-
-
-
-
-
+
+
+
+
+
+
diff --git a/client/src/app.vue b/client/src/app.vue
index dc7b4287..74503a7f 100644
--- a/client/src/app.vue
+++ b/client/src/app.vue
@@ -29,7 +29,7 @@
-
+
@@ -109,25 +109,29 @@
}
@media only screen and (max-width: 600px) {
- #neko {
- &.expanded {
- .neko-main {
- transform: translateX(-$side-width);
- }
- .neko-menu {
- transform: translateX(-$side-width);
+ #neko.expanded {
+ .neko-main {
+ transform: translateX(calc(-100% + 65px));
+
+ video {
+ display: none;
}
}
+
+ .neko-menu {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 65px;
+ width: calc(100% - 65px);
+ }
}
}
@media only screen and (max-width: 768px) {
- #neko {
- .neko-main {
- .room-container {
- display: none;
- }
- }
+ #neko .neko-main .room-container {
+ display: none;
}
}
diff --git a/client/src/components/avatar.vue b/client/src/components/avatar.vue
new file mode 100644
index 00000000..abe7c115
--- /dev/null
+++ b/client/src/components/avatar.vue
@@ -0,0 +1,58 @@
+
+
+
+ {{ seed.substring(0, 2).toUpperCase() }}
+
+
+
+
+
+
diff --git a/client/src/components/chat.vue b/client/src/components/chat.vue
index 619909af..83abf8c8 100644
--- a/client/src/components/chat.vue
+++ b/client/src/components/chat.vue
@@ -4,7 +4,7 @@
-
+
@@ -106,7 +106,7 @@
background: $style-primary;
margin: 0px 10px 10px 0px;
- img {
+ .avatar {
width: 100%;
}
}
@@ -329,6 +329,7 @@
import Markdown from './markdown'
import Content from './context.vue'
import Emoji from './emoji.vue'
+ import Avatar from './avatar.vue'
const length = 512 // max length of message
@@ -338,6 +339,7 @@
'neko-markdown': Markdown,
'neko-context': Content,
'neko-emoji': Emoji,
+ 'neko-avatar': Avatar,
},
})
export default class extends Vue {
diff --git a/client/src/components/clipboard.vue b/client/src/components/clipboard.vue
new file mode 100644
index 00000000..a1607e37
--- /dev/null
+++ b/client/src/components/clipboard.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/src/components/connect.vue b/client/src/components/connect.vue
index 7ae1962c..ab523573 100644
--- a/client/src/components/connect.vue
+++ b/client/src/components/connect.vue
@@ -6,9 +6,10 @@
n .eko