Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

packaging: add debian and homebrew releases (#437)

* docker: add ruby and fpm

* packaging: add deb files

* Makefile: fix architecture specified

* WIP aptly stuff

* Makefile: aptly publishing

* Makefile: working apt repo management

* Makefile: fiddly fixes

* Makefile: forgot to quote

* docs: add debian installation instructions

* docs: fix formatting

* test homebrew action

* test homebrew action 2

* fix ssh config from makefile

* STREAMPLACE_VERSION_OVERRIDE

* clone over ssh

* lol

* done!

authored by

Eli Mallon and committed by
GitHub
a16abc5b e78005bf

+459 -22
+1 -1
.ci/dockerfile-hash.yaml
··· 1 1 variables: 2 - DOCKERFILE_HASH: 49b462c266c7cdc7ab05eaeb02dd8e3ffb8bcb82 2 + DOCKERFILE_HASH: af492185d8fb948d84acace9029719df5d5dbf05
+13 -1
.gitlab-ci.yml
··· 71 71 script: 72 72 - rm -rf /usr/x86_64-w64-mingw32/include/d3dcompiler.h /usr/share/mingw-w64/include/d3dcompiler.h /usr/lib/gcc/x86_64-w64-mingw32/10-posix/libssp.dll.a /usr/lib/gcc/x86_64-w64-mingw32/10-posix/libssp-0.dll /usr/lib/gcc/x86_64-w64-mingw32/10-win32/libssp-0.dll /usr/lib/gcc/x86_64-w64-mingw32/10-win32/libssp.dll.a 73 73 - git fetch --unshallow || echo 'already unshallow' 74 - - bash -c "make version && make app && make $TARGET && make desktop-$TARGET && make ci-upload-node-$TARGET -j$(nproc)" 74 + - bash -c "make version && make app && make $TARGET && make desktop-$TARGET && make pkg-$TARGET && make ci-upload-node-$TARGET -j$(nproc)" 75 75 artifacts: 76 76 reports: 77 77 dotenv: .ci/build.env ··· 377 377 - .release-template 378 378 script: 379 379 - make ci-release 380 + 381 + deb-release: 382 + extends: 383 + - .release-template 384 + script: 385 + - make ci-deb-release 386 + 387 + homebrew-release: 388 + extends: 389 + - .release-template 390 + script: 391 + - make ci-homebrew 380 392 381 393 .report-status: 382 394 tags:
+125 -8
Makefile
··· 5 5 default: app node 6 6 7 7 VERSION?=$(shell go run ./pkg/config/git/git.go -v) 8 + VERSION_NO_V=$(subst v,,$(VERSION)) 8 9 VERSION_ELECTRON=$(subst -,-z,$(subst v,,$(VERSION))) 9 10 UUID?=$(shell go run ./pkg/config/uuid/uuid.go) 10 11 BRANCH?=$(shell go run ./pkg/config/git/git.go --branch) ··· 609 610 -t dist.stream.place/streamplace/streamplace:mistserver \ 610 611 . 611 612 613 + FPM_BASE_OPTS= \ 614 + -s dir \ 615 + -t deb \ 616 + -v $(VERSION_NO_V) \ 617 + --force \ 618 + --license=GPL-3.0-or-later \ 619 + --maintainer="Streamplace <support@stream.place>" \ 620 + --vendor="Streamplace" \ 621 + --url="https://stream.place" 622 + SP_ARCH_NAME?=amd64 623 + .PHONY: deb-pkg 624 + deb-pkg: 625 + fpm $(FPM_BASE_OPTS) \ 626 + -n streamplace \ 627 + -a $(SP_ARCH_NAME) \ 628 + -p bin/streamplace-$(VERSION)-linux-$(SP_ARCH_NAME).deb \ 629 + --deb-systemd=util/systemd/streamplace.service \ 630 + --deb-systemd-auto-start \ 631 + --deb-systemd-enable \ 632 + --deb-systemd-restart-after-upgrade \ 633 + --after-install=util/systemd/after-install.sh \ 634 + --description="Live video for the AT Protocol. Solving video for everybody forever." \ 635 + build-linux-$(SP_ARCH_NAME)/streamplace=/usr/bin/streamplace \ 636 + && fpm $(FPM_BASE_OPTS) \ 637 + -n streamplace-default-http \ 638 + -a $(SP_ARCH_NAME) \ 639 + -d streamplace \ 640 + --deb-systemd-auto-start \ 641 + --deb-systemd-enable \ 642 + --deb-systemd-restart-after-upgrade \ 643 + -p bin/streamplace-default-http-$(VERSION)-linux-$(SP_ARCH_NAME).deb \ 644 + --description="Installing this package will install Streamplace as the default HTTP server on ports 80 and 443." \ 645 + util/systemd/streamplace-http.socket=/lib/systemd/system/streamplace-http.socket \ 646 + util/systemd/streamplace-https.socket=/lib/systemd/system/streamplace-https.socket 647 + 648 + .PHONY: pkg-linux-amd64 649 + pkg-linux-amd64: 650 + $(MAKE) deb-pkg SP_ARCH_NAME=amd64 651 + 652 + .PHONY: pkg-linux-arm64 653 + pkg-linux-arm64: 654 + $(MAKE) deb-pkg SP_ARCH_NAME=arm64 655 + 656 + .PHONY: pkg-darwin-amd64 657 + pkg-darwin-amd64: 658 + echo todo 659 + 660 + .PHONY: pkg-darwin-arm64 661 + pkg-darwin-arm64: 662 + echo todo 663 + 664 + .PHONY: pkg-windows-amd64 665 + pkg-windows-amd64: 666 + echo todo 667 + 612 668 .PHONY: ci-upload 613 669 ci-upload: ci-upload-node ci-upload-android 614 670 615 671 .PHONY: ci-upload-node-linux-amd64 616 672 ci-upload-node-linux-amd64: 617 - export file=streamplace-$(VERSION)-linux-amd64.tar.gz \ 618 - && $(MAKE) ci-upload-file upload_file=$$file; \ 619 - export file=streamplace-desktop-$(VERSION)-linux-amd64.AppImage \ 620 - && $(MAKE) ci-upload-file upload_file=$$file; 673 + $(MAKE) ci-upload-file upload_file=streamplace-$(VERSION)-linux-amd64.tar.gz \ 674 + && $(MAKE) ci-upload-file upload_file=streamplace-desktop-$(VERSION)-linux-amd64.AppImage \ 675 + && $(MAKE) ci-upload-file upload_file=streamplace-default-http-$(VERSION)-linux-amd64.deb \ 676 + && $(MAKE) ci-upload-file upload_file=streamplace-$(VERSION)-linux-amd64.deb 621 677 622 678 .PHONY: ci-upload-node-linux-arm64 623 679 ci-upload-node-linux-arm64: 624 - export file=streamplace-$(VERSION)-linux-arm64.tar.gz \ 625 - && $(MAKE) ci-upload-file upload_file=$$file; \ 626 - export file=streamplace-desktop-$(VERSION)-linux-arm64.AppImage \ 627 - && $(MAKE) ci-upload-file upload_file=$$file; 680 + $(MAKE) ci-upload-file upload_file=streamplace-$(VERSION)-linux-arm64.tar.gz \ 681 + && $(MAKE) ci-upload-file upload_file=streamplace-desktop-$(VERSION)-linux-arm64.AppImage \ 682 + && $(MAKE) ci-upload-file upload_file=streamplace-default-http-$(VERSION)-linux-arm64.deb \ 683 + && $(MAKE) ci-upload-file upload_file=streamplace-$(VERSION)-linux-arm64.deb 628 684 629 685 .PHONY: ci-upload-node-darwin-arm64 630 686 ci-upload-node-darwin-arm64: ··· 687 743 --upload-file bin/$(upload_file) \ 688 744 "$$CI_API_V4_URL/projects/$$CI_PROJECT_ID/packages/generic/$(BRANCH)/$(VERSION)/$(upload_file)"; 689 745 746 + download_file?="" 747 + .PHONY: ci-download-file 748 + ci-download-file: 749 + curl \ 750 + --fail-with-body \ 751 + --header "JOB-TOKEN: $$CI_JOB_TOKEN" \ 752 + -o bin/$(download_file) \ 753 + "$$CI_API_V4_URL/projects/$$CI_PROJECT_ID/packages/generic/$(BRANCH)/$(VERSION)/$(download_file)"; 754 + 690 755 .PHONY: release 691 756 release: install 692 757 $(MAKE) lexicons ··· 698 763 go run ./pkg/config/git/git.go -release -o release.yml 699 764 release-cli create-from-file --file release.yml 700 765 766 + .PHONY: deb-release 767 + deb-release: 768 + aptly repo create -distribution=all -component=main streamplace-releases 769 + aptly mirror create old-version $$S3_PUBLIC_URL/debian all 770 + aptly mirror update old-version 771 + aptly repo import old-version streamplace-releases streamplace streamplace-default-http 772 + aptly repo add streamplace-releases \ 773 + bin/streamplace-default-http-$(VERSION)-linux-arm64.deb \ 774 + bin/streamplace-$(VERSION)-linux-arm64.deb \ 775 + bin/streamplace-default-http-$(VERSION)-linux-amd64.deb \ 776 + bin/streamplace-$(VERSION)-linux-amd64.deb 777 + aptly snapshot create streamplace-$(VERSION) from repo streamplace-releases 778 + aptly publish snapshot -distribution=all streamplace-$(VERSION) s3:streamplace-releases: 779 + 780 + .PHONY: ci-deb-release 781 + ci-deb-release: 782 + $(MAKE) ci-download-file download_file=streamplace-default-http-$(VERSION)-linux-amd64.deb 783 + $(MAKE) ci-download-file download_file=streamplace-$(VERSION)-linux-amd64.deb 784 + $(MAKE) ci-download-file download_file=streamplace-default-http-$(VERSION)-linux-arm64.deb 785 + $(MAKE) ci-download-file download_file=streamplace-$(VERSION)-linux-arm64.deb 786 + echo $$CI_SIGNING_KEY_BASE64 | base64 -d | gpg --import 787 + gpg --armor --export | gpg --no-default-keyring --keyring trustedkeys.gpg --import 788 + echo '{"S3PublishEndpoints":{"streamplace-releases":{"region":"'$$S3_REGION'","bucket":"'$$S3_BUCKET_NAME'","endpoint":"'$$S3_ENDPOINT'","acl":"public-read","prefix":"debian"}}}' > ~/.aptly.conf 789 + $(MAKE) deb-release 790 + 701 791 .PHONY: check 702 792 check: install 703 793 $(MAKE) golangci-lint ··· 720 810 .PHONY: rtcrec 721 811 rtcrec: 722 812 go build -o $(BUILDDIR)/rtcrec ./pkg/rtcrec/cmd/... 813 + 814 + .PHONY: homebrew 815 + homebrew: 816 + $(MAKE) ci-download-file download_file=streamplace-$(VERSION)-linux-amd64.tar.gz 817 + $(MAKE) ci-download-file download_file=streamplace-$(VERSION)-linux-arm64.tar.gz 818 + $(MAKE) ci-download-file download_file=streamplace-$(VERSION)-darwin-amd64.tar.gz 819 + $(MAKE) ci-download-file download_file=streamplace-$(VERSION)-darwin-arm64.tar.gz 820 + git clone git@github.com:streamplace/homebrew-streamplace.git /tmp/homebrew-streamplace 821 + go run ./pkg/config/git/git.go -homebrew -o /tmp/homebrew-streamplace/Formula/streamplace.rb 822 + 823 + .PHONY: ci-homebrew 824 + ci-homebrew: 825 + git config --global user.name "Streamplace Homebrew Robot" 826 + git config --global user.email support@stream.place 827 + mkdir -p ~/.ssh 828 + echo "Host * \n\ 829 + StrictHostKeyChecking no \n\ 830 + UserKnownHostsFile=/dev/null" > ~/.ssh/config 831 + echo "$$CI_HOMEBREW_KEY_BASE64" | base64 -d > ~/.ssh/id_ed25519 832 + chmod 600 ~/.ssh/id_ed25519 833 + 834 + chmod 600 ~/.ssh/config 835 + $(MAKE) homebrew 836 + cd /tmp/homebrew-streamplace \ 837 + && git add . \ 838 + && git commit -m "Update streamplace $(VERSION)" \ 839 + && git push
+8
docker/build.Dockerfile
··· 35 35 mono-runtime nuget mono-xsp4 squashfs-tools \ 36 36 libc6:arm64 libstdc++6:arm64 \ 37 37 cmake libssl-dev libssl-dev:arm64 \ 38 + ruby-rubygems \ 38 39 && pip install meson tomli \ 39 40 && curl -L --fail https://go.dev/dl/go$GO_VERSION.linux-$TARGETARCH.tar.gz -o go.tar.gz \ 40 41 && tar -C /usr/local -xf go.tar.gz \ ··· 92 93 && tar -xf golangci-lint.tar.gz \ 93 94 && mv golangci-lint-2.1.6-linux-amd64/golangci-lint /usr/local/bin/ \ 94 95 && rm -rf golangci-lint.tar.gz golangci-lint-2.1.6-linux-amd64 96 + 97 + RUN gem install fpm 98 + ENV APTLY_VERSION 1.6.2 99 + RUN curl --fail -L https://github.com/aptly-dev/aptly/releases/download/v${APTLY_VERSION}/aptly_${APTLY_VERSION}_linux_amd64.zip -o aptly.zip \ 100 + && unzip aptly.zip \ 101 + && mv aptly_${APTLY_VERSION}_linux_amd64/aptly /usr/local/bin/ \ 102 + && rm -rf aptly.zip aptly_${APTLY_VERSION}_linux_amd64 95 103 96 104 ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=false 97 105
+4
js/docs/astro.config.mjs
··· 50 50 autogenerate: { directory: "guides/start-streaming" }, 51 51 }, 52 52 { 53 + label: "Installing Streamplace", 54 + autogenerate: { directory: "guides/installing" }, 55 + }, 56 + { 53 57 label: "Start Contributing", 54 58 autogenerate: { directory: "guides/start-contributing" }, 55 59 },
+43
js/docs/src/content/docs/guides/installing/downloading-streamplace.md
··· 1 + --- 2 + title: Downloading Streamplace 3 + description: How to download Streamplace 4 + sidebar: 5 + order: 20 6 + --- 7 + 8 + ## macOS 9 + 10 + ```shell 11 + brew install streamplace/streamplace/streamplace 12 + ``` 13 + 14 + ## Linux 15 + 16 + We distribute two Linux packages for Streamplace: 17 + 18 + - `streamplace`, which is the main Streamplace binary. 19 + - `streamplace-default-http`, which includes some additional systemd 20 + configuration to make Streamplace your default HTTP server on ports 80 21 + and 443. 22 + 23 + If you're looking to set up a Streamplace node on a server that isn't hosting 24 + any other services, we'd recommend e.g. 25 + `apt install streamplace streamplace-default-http`. If your server is hosting 26 + other HTTP servers and you'll handle the proxying yourself, you can simply 27 + `apt install streamplace`. 28 + 29 + ### Debian/Ubuntu 30 + 31 + ```shell 32 + sudo mkdir -p /etc/apt/keyrings 33 + curl https://release.stream.place/streamplace.key | sudo gpg --dearmor -o /etc/apt/keyrings/streamplace.key 34 + echo 'deb [signed-by=/etc/apt/keyrings/streamplace.key] https://release.stream.place/debian/ all main' \ 35 + | sudo tee /etc/apt/sources.list.d/streamplace.list 36 + sudo apt update 37 + sudo apt install streamplace 38 + ``` 39 + 40 + ## Download a binary 41 + 42 + Binaries for all platforms are available to download from 43 + [our GitLab server](https://git.stream.place/streamplace/streamplace/-/releases).
+4 -3
js/docs/src/content/docs/index.mdx
··· 22 22 ## Next Steps 23 23 24 24 <CardGrid> 25 - <Card title="Start Streaming" icon="rss"> 26 - Stream live, on the ATProtocol. 27 - </Card> 28 25 <Card title="Read the Docs" icon="open-book"> 29 26 Learn how to start streaming with 30 27 [Streamplace](/docs/guides/start-streaming/obs). 28 + </Card> 29 + <Card title="Install Streamplace" icon="download"> 30 + [Run your own Streamplace 31 + node](/docs/guides/installing/installing-streamplace). 31 32 </Card> 32 33 <Card title="API Reference" icon="document"> 33 34 Explore the [Lexicon API reference](/docs/lex-reference/place-stream-defs).
+58 -9
pkg/api/api.go
··· 12 12 "net/http/httputil" 13 13 "net/url" 14 14 "os" 15 + "strconv" 15 16 "strings" 16 17 "sync" 17 18 "time" ··· 720 721 } 721 722 } 722 723 724 + // helper for getting a listener from a systemd file descriptor 725 + func getListenerFromFD(fdName string) (net.Listener, error) { 726 + log.Log(context.TODO(), "getting listener from fd", "fdName", fdName, "LISTEN_PID", os.Getenv("LISTEN_PID"), "LISTEN_FDNAMES", os.Getenv("LISTEN_FDNAMES")) 727 + if os.Getenv("LISTEN_PID") == strconv.Itoa(os.Getpid()) { 728 + names := strings.Split(os.Getenv("LISTEN_FDNAMES"), ":") 729 + for i, name := range names { 730 + if name == fdName { 731 + f1 := os.NewFile(uintptr(i+3), fdName) 732 + return net.FileListener(f1) 733 + } 734 + } 735 + } 736 + return nil, nil 737 + } 738 + 723 739 func (a *StreamplaceAPI) ServeHTTP(ctx context.Context) error { 724 740 handler, err := a.Handler(ctx) 725 741 if err != nil { 726 742 return err 727 743 } 728 744 return a.ServerWithShutdown(ctx, handler, func(s *http.Server) error { 729 - s.Addr = a.CLI.HTTPAddr 730 - log.Log(ctx, "http server starting", "addr", s.Addr) 731 - return s.ListenAndServe() 745 + ln, err := getListenerFromFD("http") 746 + if err != nil { 747 + return err 748 + } 749 + if ln == nil { 750 + ln, err = net.Listen("tcp", a.CLI.HTTPAddr) 751 + if err != nil { 752 + return err 753 + } 754 + } else { 755 + log.Warn(ctx, "api server listening for http over systemd socket", "addr", ln.Addr()) 756 + } 757 + log.Log(ctx, "http server starting", "addr", ln.Addr()) 758 + return s.Serve(ln) 732 759 }) 733 760 } 734 761 ··· 738 765 return err 739 766 } 740 767 return a.ServerWithShutdown(ctx, handler, func(s *http.Server) error { 741 - s.Addr = a.CLI.HTTPAddr 742 - log.Log(ctx, "http tls redirecct server starting", "addr", s.Addr) 743 - return s.ListenAndServe() 768 + ln, err := getListenerFromFD("http") 769 + if err != nil { 770 + return err 771 + } 772 + if ln == nil { 773 + ln, err = net.Listen("tcp", a.CLI.HTTPAddr) 774 + if err != nil { 775 + return err 776 + } 777 + } else { 778 + log.Warn(ctx, "http tls redirect server listening for http over systemd socket", "addr", ln.Addr()) 779 + } 780 + log.Log(ctx, "http tls redirect server starting", "addr", ln.Addr()) 781 + return s.Serve(ln) 744 782 }) 745 783 } 746 784 ··· 750 788 return err 751 789 } 752 790 return a.ServerWithShutdown(ctx, handler, func(s *http.Server) error { 753 - s.Addr = a.CLI.HTTPSAddr 791 + ln, err := getListenerFromFD("https") 792 + if err != nil { 793 + return err 794 + } 795 + if ln == nil { 796 + ln, err = net.Listen("tcp", a.CLI.HTTPSAddr) 797 + if err != nil { 798 + return err 799 + } 800 + } else { 801 + log.Warn(ctx, "https server listening for https over systemd socket", "addr", ln.Addr()) 802 + } 754 803 log.Log(ctx, "https server starting", 755 - "addr", s.Addr, 804 + "addr", ln.Addr(), 756 805 "certPath", a.CLI.TLSCertPath, 757 806 "keyPath", a.CLI.TLSKeyPath, 758 807 ) 759 - return s.ListenAndServeTLS(a.CLI.TLSCertPath, a.CLI.TLSKeyPath) 808 + return s.ServeTLS(ln, a.CLI.TLSCertPath, a.CLI.TLSKeyPath) 760 809 }) 761 810 } 762 811
+101
pkg/config/git/git.go
··· 1 1 package main 2 2 3 3 import ( 4 + "bytes" 5 + "crypto/sha256" 4 6 "encoding/json" 5 7 "flag" 6 8 "fmt" 9 + "io" 7 10 "math/rand" 8 11 "net/http" 9 12 "os" 10 13 "sort" 11 14 "strings" 15 + "text/template" 12 16 13 17 "github.com/go-git/go-git/v5" 14 18 "github.com/go-git/go-git/v5/plumbing" ··· 75 79 doBranch := flag.Bool("branch", false, "print branch") 76 80 doRelease := flag.Bool("release", false, "print release json file") 77 81 javascript := flag.Bool("js", false, "print code in javascript format") 82 + homebrew := flag.Bool("homebrew", false, "print homebrew formula") 78 83 79 84 flag.Parse() 80 85 r, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true}) ··· 163 168 out = string(bs) 164 169 } else if *javascript { 165 170 out = fmt.Sprintf(tmplJS, desc, ts, u) 171 + } else if *homebrew { 172 + bs := bytes.Buffer{} 173 + versionNoV := strings.TrimPrefix(desc, "v") 174 + darwinAmd64File := fmt.Sprintf("streamplace-%s-darwin-amd64.tar.gz", desc) 175 + darwinArm64File := fmt.Sprintf("streamplace-%s-darwin-arm64.tar.gz", desc) 176 + linuxAmd64File := fmt.Sprintf("streamplace-%s-linux-amd64.tar.gz", desc) 177 + linuxArm64File := fmt.Sprintf("streamplace-%s-linux-arm64.tar.gz", desc) 178 + 179 + err = homebrewTmpl.Execute(&bs, Homebrew{ 180 + Version: versionNoV, 181 + DarwinArm64: getHash(darwinArm64File), 182 + DarwinAmd64: getHash(darwinAmd64File), 183 + LinuxArm64: getHash(linuxArm64File), 184 + LinuxAmd64: getHash(linuxAmd64File), 185 + }) 186 + if err != nil { 187 + return err 188 + } 189 + out = bs.String() 166 190 } else { 167 191 out = fmt.Sprintf(tmpl, desc, ts, u) 168 192 } ··· 177 201 return nil 178 202 } 179 203 204 + func getHash(fileName string) string { 205 + filePath := fmt.Sprintf("bin/%s", fileName) 206 + f, err := os.Open(filePath) 207 + if err != nil { 208 + panic(err) 209 + } 210 + defer f.Close() 211 + 212 + h := sha256.New() 213 + buf := make([]byte, 1024*1024) // 1MB buffer 214 + 215 + for { 216 + n, err := f.Read(buf) 217 + if n > 0 { 218 + if _, err := h.Write(buf[:n]); err != nil { 219 + panic(err) 220 + } 221 + } 222 + if err != nil { 223 + if err == io.EOF { 224 + break 225 + } 226 + panic(err) 227 + } 228 + } 229 + 230 + return fmt.Sprintf("%x", h.Sum(nil)) 231 + } 232 + 180 233 func branch() string { 181 234 CICommitTag := os.Getenv("CI_COMMIT_TAG") 182 235 CICommitBranch := os.Getenv("CI_COMMIT_BRANCH") ··· 226 279 227 280 // Describe the reference as 'git describe --tags' will do 228 281 func (g *Git) Describe(reference *plumbing.Reference) (string, error) { 282 + if os.Getenv("STREAMPLACE_VERSION_OVERRIDE") != "" { 283 + return os.Getenv("STREAMPLACE_VERSION_OVERRIDE"), nil 284 + } 229 285 230 286 // Fetch the reference log 231 287 cIter, err := g.Log(&git.LogOptions{ ··· 270 326 ), nil 271 327 } 272 328 } 329 + 330 + type Homebrew struct { 331 + Version string 332 + DarwinArm64 string 333 + DarwinAmd64 string 334 + LinuxArm64 string 335 + LinuxAmd64 string 336 + } 337 + 338 + var homebrewTmpl = template.Must(template.New("homebrew").Parse(` 339 + class Streamplace < Formula 340 + desc "Live video for the AT Protocol. Solving video for everybody forever." 341 + homepage "https://stream.place" 342 + license "GPL-3.0-or-later" 343 + version "{{.Version}}" 344 + 345 + on_macos do 346 + if Hardware::CPU.arm? 347 + url "https://git-cloudflare.stream.place/api/v4/projects/1/packages/generic/latest/v{{.Version}}/streamplace-v{{.Version}}-darwin-arm64.tar.gz" 348 + sha256 "{{.DarwinArm64}}" 349 + end 350 + 351 + if Hardware::CPU.intel? 352 + url "https://git-cloudflare.stream.place/api/v4/projects/1/packages/generic/latest/v{{.Version}}/streamplace-v{{.Version}}-darwin-amd64.tar.gz" 353 + sha256 "{{.DarwinAmd64}}" 354 + end 355 + end 356 + 357 + on_linux do 358 + if Hardware::CPU.arm? && Hardware::CPU.is_64_bit? 359 + url "https://git-cloudflare.stream.place/api/v4/projects/1/packages/generic/latest/v{{.Version}}/streamplace-v{{.Version}}-linux-arm64.tar.gz" 360 + sha256 "{{.LinuxArm64}}" 361 + end 362 + 363 + if Hardware::CPU.intel? 364 + url "https://git-cloudflare.stream.place/api/v4/projects/1/packages/generic/latest/v{{.Version}}/streamplace-v{{.Version}}-linux-amd64.tar.gz" 365 + sha256 "{{.LinuxAmd64}}" 366 + end 367 + end 368 + 369 + def install 370 + bin.install "streamplace" => "streamplace" 371 + end 372 + end 373 + `))
+23
util/systemd/after-install.sh
··· 1 + #!/bin/sh 2 + 3 + set -e 4 + 5 + # Create streamplace group if it doesn't exist 6 + if ! getent group streamplace >/dev/null; then 7 + groupadd streamplace 8 + fi 9 + 10 + # Create streamplace user if it doesn't exist 11 + if ! getent passwd streamplace >/dev/null; then 12 + useradd -r -g streamplace -d /var/lib/streamplace -s /sbin/nologin streamplace 13 + fi 14 + 15 + mkdir -p /var/lib/streamplace 16 + mkdir -p /etc/streamplace 17 + chown -R streamplace:streamplace /var/lib/streamplace 18 + 19 + # Create default environment file if it doesn't exist 20 + if [ ! -f /etc/streamplace/streamplace.env ]; then 21 + echo "# Configure your Streamplace instance by creating lines such as:" > /etc/streamplace/streamplace.env 22 + echo "# SP_PUBLIC_HOST=example.com" >> /etc/streamplace/streamplace.env 23 + fi
+10
util/systemd/streamplace-http.socket
··· 1 + [Unit] 2 + Description=streamplace http socket 3 + 4 + [Socket] 5 + ListenStream=80 6 + FileDescriptorName=http 7 + Service=streamplace.service 8 + 9 + [Install] 10 + WantedBy=sockets.target
+10
util/systemd/streamplace-https.socket
··· 1 + [Unit] 2 + Description=streamplace https socket 3 + 4 + [Socket] 5 + ListenStream=443 6 + FileDescriptorName=https 7 + Service=streamplace.service 8 + 9 + [Install] 10 + WantedBy=sockets.target
+59
util/systemd/streamplace.service
··· 1 + [Unit] 2 + Description=Live video for the AT Protocol. Solving video for everybody forever. 3 + Documentation=https://stream.place/docs 4 + After=network-online.target 5 + Wants=network-online.target 6 + Wants=streamplace-http.socket streamplace-https.socket 7 + Requires=network.target 8 + 9 + [Service] 10 + Type=exec 11 + ExecStart=/usr/bin/streamplace 12 + Restart=always 13 + RestartSec=3 14 + TimeoutStartSec=60 15 + TimeoutStopSec=30 16 + 17 + User=streamplace 18 + Group=streamplace 19 + 20 + # Environment 21 + Environment=SP_DATA_DIR=/var/lib/streamplace 22 + 23 + # Additional environment file for user customization 24 + EnvironmentFile=-/etc/streamplace/streamplace.env 25 + 26 + # Security hardening 27 + NoNewPrivileges=yes 28 + ProtectSystem=strict 29 + ProtectHome=yes 30 + ProtectKernelTunables=yes 31 + ProtectKernelModules=yes 32 + ProtectControlGroups=yes 33 + RestrictRealtime=yes 34 + RestrictSUIDSGID=yes 35 + RemoveIPC=yes 36 + PrivateTmp=yes 37 + 38 + # Allow access to necessary directories 39 + ReadWritePaths=/var/lib/streamplace 40 + ReadOnlyPaths=/etc/streamplace 41 + 42 + # Network access 43 + PrivateNetwork=no 44 + RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX 45 + 46 + # Resource limits 47 + LimitNOFILE=65536 48 + LimitNPROC=4096 49 + 50 + # Logging 51 + StandardOutput=journal 52 + StandardError=journal 53 + SyslogIdentifier=streamplace 54 + 55 + # Working directory 56 + WorkingDirectory=/var/lib/streamplace 57 + 58 + [Install] 59 + WantedBy=multi-user.target