11 Commits

Author SHA1 Message Date
792b1ac111 remove any temporary files associated with a Form, fixes #347. 2023-12-26 15:49:16 +01:00
a03b29ba01 add version sort to get the latest version, fixes #348. 2023-12-26 15:43:50 +01:00
683b750189 move proxy option to server. 2023-11-19 14:50:23 +01:00
3c4d7b9d60 upgrade go-chi to v5. 2023-10-15 13:18:43 +02:00
7a9b33706a chore: remove refs to deprecated io/ioutil (#329) 2023-08-31 13:32:16 +02:00
052a961fd9 fix docs #327, 2023-08-26 21:13:20 +01:00
8ef9c1aff5 add firefox nvidia image to docs. 2023-06-26 17:39:34 +02:00
6ed3493aa0 update LICENCE. 2023-05-11 00:42:12 +02:00
5959d056f3 Fix arm build (#302)
* WIP.

* WIP.

* WIP.
2023-04-29 18:35:11 +02:00
92ad202bfe Add version to docker build (#301)
* add version to build.

* update docs.
2023-04-29 00:12:56 +02:00
cd4acb5eec lang url parameter (#296)
* lang url parameter

* add ?lang to readme.

---------

Co-authored-by: Miroslav Šedivý <sedivy.miro@gmail.com>
2023-04-22 01:24:23 +02:00
27 changed files with 149 additions and 82 deletions

View File

@ -27,7 +27,7 @@ RUN set -eux; apt-get update; \
#
# build server
COPY server/ .
RUN go get -v -t -d . && go build -o bin/neko cmd/neko/main.go
RUN ./build
#
# STAGE 2: CLIENT

View File

@ -27,29 +27,32 @@ RUN set -eux; apt-get update; \
#
# build server
COPY server/ .
RUN go get -v -t -d . && go build -o bin/neko cmd/neko/main.go
RUN ./build
#
# STAGE 2: CLIENT
#
FROM node:18-bullseye-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
# Because client builds fail in Github Actions, therefor we build it outside of Docker.
#
# FROM node:18-bullseye-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
#
# build client
COPY client/ .
RUN npm run build
#
# STAGE 3: RUNTIME
#
@ -134,7 +137,8 @@ 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
# COPY --from=client /src/dist/ /var/www
COPY client/dist/ /var/www
HEALTHCHECK --interval=10s --timeout=5s --retries=8 \
CMD wget -O - http://localhost:${NEKO_BIND#*:}/health || exit 1

View File

@ -27,7 +27,7 @@ RUN set -eux; apt-get update; \
#
# build server
COPY server/ .
RUN go get -v -t -d . && go build -o bin/neko cmd/neko/main.go
RUN ./build
#
# STAGE 2: CLIENT

View File

@ -82,7 +82,7 @@ RUN set -eux; apt-get update; \
#
# build server
COPY server/ .
RUN go get -v -t -d . && go build -o bin/neko cmd/neko/main.go
RUN ./build
#
# STAGE 2: CLIENT

View File

@ -10,7 +10,7 @@ RUN set -eux; \
#
# install widevine module
CHROMIUM_DIR="/usr/lib/chromium"; \
WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | tail -n 1); \
WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | sort --version-sort | tail -n 1); \
wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/${WIDEVINE_VERSION}-linux-x64.zip"; \
mkdir -p "${CHROMIUM_DIR}/WidevineCdm/_platform_specific/linux_x64"; \
unzip -p /tmp/widevine.zip LICENSE.txt > "${CHROMIUM_DIR}/WidevineCdm/LICENSE"; \

View File

@ -14,7 +14,7 @@ RUN set -eux; \
#
# install widevine module
CHROMIUM_DIR="/usr/lib/chromium"; \
WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | tail -n 1); \
WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | sort --version-sort | tail -n 1); \
wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/${WIDEVINE_VERSION}-linux-x64.zip"; \
mkdir -p "${CHROMIUM_DIR}/WidevineCdm/_platform_specific/linux_x64"; \
unzip -p /tmp/widevine.zip LICENSE.txt > "${CHROMIUM_DIR}/WidevineCdm/LICENSE"; \

View File

@ -8,7 +8,7 @@ ARG API_URL="https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edg
RUN set -eux; apt-get update; \
#
# fetch latest release
SRC_URL="${API_URL}$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"]*\).*/\1/p' | tail -1)"; \
SRC_URL="${API_URL}$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"]*\).*/\1/p' | sort --version-sort | tail -1)"; \
wget -O /tmp/microsoft-edge.deb "${SRC_URL}"; \
apt-get install -y --no-install-recommends openbox /tmp/microsoft-edge.deb; \
#

View File

@ -8,7 +8,7 @@ ARG API_URL="https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edg
RUN set -eux; apt-get update; \
#
# fetch latest release
SRC_URL="${API_URL}$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"]*\).*/\1/p' | tail -1)"; \
SRC_URL="${API_URL}$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"]*\).*/\1/p' | sort --version-sort | tail -1)"; \
wget -O /tmp/microsoft-edge.deb "${SRC_URL}"; \
apt-get install -y --no-install-recommends openbox /tmp/microsoft-edge.deb; \
#

View File

@ -9,7 +9,7 @@ ARG LIBFFMPEG_API_URL="https://api.github.com/repos/nwjs-ffmpeg-prebuilt/nwjs-ff
RUN set -eux; apt-get update; \
#
# fetch latest release
VERSION="$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"/]*\).*/\1/p' | tail -1)"; \
VERSION="$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"/]*\).*/\1/p' | sort --version-sort | tail -1)"; \
wget -O /tmp/opera.deb "${API_URL}${VERSION}/linux/opera-stable_${VERSION}_amd64.deb"; \
apt-get install -y --no-install-recommends openbox jq unzip /tmp/opera.deb; \
#

View File

@ -21,7 +21,7 @@ RUN set -eux; apt-get update; \
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); \
WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | sort --version-sort | 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; \

View File

@ -13,7 +13,7 @@ env:
PLATFORMS: linux/arm64,linux/arm/v7
jobs:
build-base:
build-client:
runs-on: ubuntu-latest
#
# do not run on forks
@ -23,6 +23,41 @@ jobs:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up node
uses: actions/setup-node@v3
with:
node-version: 18.x
-
name: Build client
run: |
cd client
npm install
npm run build
-
name: Upload client dist
uses: actions/upload-artifact@v3
with:
name: client-dist
path: client/dist
build-base:
runs-on: ubuntu-latest
#
# do not run on forks
#
if: github.repository_owner == 'm1k1o'
needs: [ build-client ]
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Download client dist
uses: actions/download-artifact@v3
with:
name: client-dist
path: client/dist
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1

View File

@ -186,7 +186,9 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 Nurdism <nurdism.io@gmail.com>, 2020-2021 m1k1o
Copyright (C) 2020 Nurdism <nurdism.io@gmail.com>
Copyright (C) 2020-2023 m1k1o
All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -76,5 +76,12 @@
about() {
this.$accessor.client.toggleAbout()
}
mounted() {
const default_lang = new URL(location.href).searchParams.get('lang')
if (default_lang && this.langs.includes(default_lang)) {
this.$i18n.locale = default_lang
}
}
}
</script>

View File

@ -6,5 +6,6 @@ Vue.use(VueI18n)
export const i18n = new VueI18n({
locale: 'en',
fallbackLocale: 'en',
messages,
})

View File

@ -4,6 +4,10 @@
### New Features
- Added nvidia support for firefox.
- Added `?lang=<lang>` parameter to the URL, which will set the language of the interface (by @mbattista).
### Misc
- Git commit and tag are now included in the build when creating a docker image.
## [n.eko v2.8.0](https://github.com/m1k1o/neko/releases/tag/v2.8.0)

View File

@ -50,7 +50,7 @@ All images are also available on [GitHub Container Registry](https://github.com/
- `ghcr.io/m1k1o/neko/xfce:latest`
- `ghcr.io/m1k1o/neko/kde:latest`
For ARM-based images (like Raspberry Pi - with GPU hardware acceleration, Oracle Cloud ARM tier). Currently, not all images are available for ARM, because not all applications are available for ARM.
For ARM-based images (like Raspberry Pi - with GPU hardware acceleration, Oracle Cloud ARM tier). Currently, not all images are available for ARM, because not all applications are available for ARM. Please note, that `m1k1o/neko:arm-*` images from dockerhub are currently not maintained and they can contain outdated software. Please use images below:
- `ghcr.io/m1k1o/neko/arm-firefox:latest`
- `ghcr.io/m1k1o/neko/arm-chromium:latest`
@ -74,8 +74,9 @@ For images with VAAPI GPU hardware acceleration using intel drivers use:
- `ghcr.io/m1k1o/neko/intel-xfce:latest`
- `ghcr.io/m1k1o/neko/intel-kde:latest`
For images with Nvidia GPU hardware acceleration using EGL (see example below) use:
For images with Nvidia GPU hardware acceleration using EGL (see example below) use (please note, there is a known issue with EGL and Chromium-based browsers, see [here](https://github.com/m1k1o/neko/issues/279)):
- `ghcr.io/m1k1o/neko/nvidia-firefox:latest`
- `ghcr.io/m1k1o/neko/nvidia-chromium:latest`
- `ghcr.io/m1k1o/neko/nvidia-google-chrome:latest`
- `ghcr.io/m1k1o/neko/nvidia-microsoft-edge:latest`
@ -255,6 +256,7 @@ NEKO_BROADCAST_PIPELINE: "flvmux name=mux ! rtmpsink location={url} pulsesrc dev
- Adding `?cast=1` will hide all control and show only video.
- Adding `?embed=1` will hide most additional components and show only video.
- Adding `?volume=<0-1>` will set volume to given value.
- Adding `?lang=<language>` will set language to given value.
- e.g. `http(s)://<URL:Port>/?pwd=neko&usr=guest&cast=1`
### Screen size

View File

@ -72,7 +72,8 @@ services:
version: "3.4"
services:
neko:
image: "m1k1o/neko:arm-chromium"
# see docs for more variants
image: "ghcr.io/m1k1o/neko/arm-chromium:latest"
restart: "unless-stopped"
# increase on rpi's with more then 1gb ram.
shm_size: "520mb"

View File

@ -1,24 +1,35 @@
#!/bin/bash
set -ex
#
# aborting if any command returns a non-zero value
set -e
BUILD_TIME=`date -u +'%Y-%m-%dT%H:%M:%SZ'`
#
# set git build variables if git exists
if git status > /dev/null 2>&1 && [ -z $GIT_COMMIT ] && [ -z $GIT_BRANCH ] && [ -z $GIT_DIRTY ];
if git status > /dev/null 2>&1 && [ -z $GIT_COMMIT ] && [ -z $GIT_BRANCH ] && [ -z $GIT_TAG ];
then
GIT_COMMIT=`git rev-parse --short HEAD`
GIT_BRANCH=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
GIT_TAG=`git tag --points-at $GIT_COMMIT | head -n 1`
GIT_DIRTY=`git diff-index --quiet HEAD -- || echo "✗-"`
GIT_COMMIT="${GIT_DIRTY}${GIT_COMMIT}"
fi
#
# load dependencies
go get -v -t -d .
#
# build server
go build \
-o bin/neko \
-ldflags "
-s -w
-X 'm1k1o/neko.buildDate=${BUILD_TIME}'
-X 'm1k1o/neko.gitCommit=${GIT_DIRTY}${GIT_COMMIT}'
-X 'm1k1o/neko.gitCommit=${GIT_COMMIT}'
-X 'm1k1o/neko.gitBranch=${GIT_BRANCH}'
-X 'm1k1o/neko.gitTag=${GIT_TAG}'
" \
cmd/neko/main.go;

View File

@ -4,7 +4,7 @@ go 1.20
require (
github.com/fsnotify/fsnotify v1.6.0
github.com/go-chi/chi v4.1.2+incompatible
github.com/go-chi/chi/v5 v5.0.10
github.com/go-chi/cors v1.2.1
github.com/gorilla/websocket v1.5.0
github.com/pion/ice/v2 v2.3.0

View File

@ -63,8 +63,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=

View File

@ -14,6 +14,7 @@ type Server struct {
Cert string
Key string
Bind string
Proxy bool
Static string
PathPrefix string
CORS []string
@ -35,6 +36,11 @@ func (Server) Init(cmd *cobra.Command) error {
return err
}
cmd.PersistentFlags().Bool("proxy", false, "enable reverse proxy mode")
if err := viper.BindPFlag("proxy", cmd.PersistentFlags().Lookup("proxy")); err != nil {
return err
}
cmd.PersistentFlags().String("static", "./www", "path to neko client files to serve")
if err := viper.BindPFlag("static", cmd.PersistentFlags().Lookup("static")); err != nil {
return err
@ -57,6 +63,7 @@ func (s *Server) Set() {
s.Cert = viper.GetString("cert")
s.Key = viper.GetString("key")
s.Bind = viper.GetString("bind")
s.Proxy = viper.GetBool("proxy")
s.Static = viper.GetString("static")
s.PathPrefix = path.Join("/", path.Clean(viper.GetString("path_prefix")))

View File

@ -10,7 +10,6 @@ import (
type WebSocket struct {
Password string
AdminPassword string
Proxy bool
Locks []string
ControlProtection bool
@ -30,11 +29,6 @@ func (WebSocket) Init(cmd *cobra.Command) error {
return err
}
cmd.PersistentFlags().Bool("proxy", false, "enable reverse proxy mode")
if err := viper.BindPFlag("proxy", cmd.PersistentFlags().Lookup("proxy")); err != nil {
return err
}
cmd.PersistentFlags().StringSlice("locks", []string{}, "resources, that will be locked when starting (control, login)")
if err := viper.BindPFlag("locks", cmd.PersistentFlags().Lookup("locks")); err != nil {
return err
@ -63,7 +57,6 @@ func (WebSocket) Init(cmd *cobra.Command) error {
func (s *WebSocket) Set() {
s.Password = viper.GetString("password")
s.AdminPassword = viper.GetString("password_admin")
s.Proxy = viper.GetBool("proxy")
s.Locks = viper.GetStringSlice("locks")
s.ControlProtection = viper.GetBool("control_protection")

View File

@ -11,8 +11,8 @@ import (
"regexp"
"strconv"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
@ -35,6 +35,9 @@ func New(conf *config.Server, webSocketHandler types.WebSocketHandler, desktop t
router := chi.NewRouter()
router.Use(middleware.RequestID) // Create a request ID for each request
if conf.Proxy {
router.Use(middleware.RealIP)
}
router.Use(middleware.RequestLogger(&logformatter{logger}))
router.Use(middleware.Recoverer) // Recover from panics without crashing server
router.Use(middleware.Compress(5, "application/octet-stream"))
@ -163,7 +166,13 @@ func New(conf *config.Server, webSocketHandler types.WebSocketHandler, desktop t
return
}
r.ParseMultipartForm(32 << 20)
err = r.ParseMultipartForm(32 << 20)
if err != nil || r.MultipartForm == nil {
logger.Warn().Err(err).Msg("failed to parse multipart form")
http.Error(w, "error parsing form", http.StatusBadRequest)
return
}
for _, formheader := range r.MultipartForm.File["files"] {
filePath := webSocketHandler.FileTransferPath(formheader.Filename)
@ -184,6 +193,11 @@ func New(conf *config.Server, webSocketHandler types.WebSocketHandler, desktop t
io.Copy(f, formfile)
}
err = r.MultipartForm.RemoveAll()
if err != nil {
logger.Warn().Err(err).Msg("failed to remove multipart form")
}
})
}

View File

@ -5,7 +5,7 @@ import (
"net/http"
"time"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5/middleware"
"github.com/rs/zerolog"
)

View File

@ -2,7 +2,7 @@ package utils
import (
"bytes"
"io/ioutil"
"io"
"net"
"net/http"
"time"
@ -31,21 +31,10 @@ func GetIP(serverUrl string) (string, error) {
}
defer rsp.Body.Close()
buf, err := ioutil.ReadAll(rsp.Body)
buf, err := io.ReadAll(rsp.Body)
if err != nil {
return "", err
}
return string(bytes.TrimSpace(buf)), nil
}
func GetHttpRequestIP(r *http.Request, proxy bool) string {
IPAddress := r.Header.Get("X-Real-Ip")
if IPAddress == "" {
IPAddress = r.Header.Get("X-Forwarded-For")
}
if IPAddress == "" || !proxy {
IPAddress = r.RemoteAddr
}
return IPAddress
}

View File

@ -290,7 +290,7 @@ func (ws *WebSocketHandler) Upgrade(w http.ResponseWriter, r *http.Request) erro
socket := &WebSocket{
id: id,
ws: ws,
address: utils.GetHttpRequestIP(r, ws.conf.Proxy),
address: r.RemoteAddr,
connection: connection,
}

View File

@ -5,6 +5,7 @@ import (
"os"
"os/signal"
"runtime"
"strings"
"m1k1o/neko/internal/capture"
"m1k1o/neko/internal/config"
@ -25,7 +26,7 @@ const Header = `&34
/ |/ / _ \/ //_/ __ \ ) ( ')
/ /| / __/ ,< / /_/ / ( / )
/_/ |_/\___/_/|_|\____/ \(__)|
&1&37 nurdism/m1k1o &33%s v%s&0
&1&37 nurdism/m1k1o &33%s %s&0
`
var (
@ -35,13 +36,8 @@ var (
gitCommit = "dev"
//
gitBranch = "dev"
// Major version when you make incompatible API changes,
major = "2"
// Minor version when you add functionality in a backwards-compatible manner, and
minor = "8"
// Patch version when you make backwards-compatible bug fixes.
patch = "0"
//
gitTag = "dev"
)
var Service *Neko
@ -49,11 +45,9 @@ var Service *Neko
func init() {
Service = &Neko{
Version: &Version{
Major: major,
Minor: minor,
Patch: patch,
GitCommit: gitCommit,
GitBranch: gitBranch,
GitTag: gitTag,
BuildDate: buildDate,
GoVersion: runtime.Version(),
Compiler: runtime.Compiler,
@ -69,11 +63,9 @@ func init() {
}
type Version struct {
Major string
Minor string
Patch string
GitCommit string
GitBranch string
GitTag string
BuildDate string
GoVersion string
Compiler string
@ -81,20 +73,25 @@ type Version struct {
}
func (i *Version) String() string {
return fmt.Sprintf("%s.%s.%s %s", i.Major, i.Minor, i.Patch, i.GitCommit)
version := i.GitTag
if version == "" || version == "dev" {
version = i.GitBranch
}
return fmt.Sprintf("%s@%s", version, i.GitCommit)
}
func (i *Version) Details() string {
return fmt.Sprintf(
"%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
fmt.Sprintf("Version %s.%s.%s", i.Major, i.Minor, i.Patch),
return "\n" + strings.Join([]string{
fmt.Sprintf("Version %s", i.String()),
fmt.Sprintf("GitCommit %s", i.GitCommit),
fmt.Sprintf("GitBranch %s", i.GitBranch),
fmt.Sprintf("GitTag %s", i.GitTag),
fmt.Sprintf("BuildDate %s", i.BuildDate),
fmt.Sprintf("GoVersion %s", i.GoVersion),
fmt.Sprintf("Compiler %s", i.Compiler),
fmt.Sprintf("Platform %s", i.Platform),
)
}, "\n") + "\n"
}
type Neko struct {