Compare commits
93 Commits
feature-th
...
master
Author | SHA1 | Date | |
---|---|---|---|
9bbfef4c39 | |||
b796f72abc | |||
22e4b4d5a4 | |||
7fbdfac786 | |||
131e84bd17 | |||
2906fb1b88 | |||
e9bd63decb | |||
9c6215d9a1 | |||
aa539af15d | |||
3dbafe08e7 | |||
d081a79f6d | |||
419686eb0c | |||
aa2b945765 | |||
e49b97a80a | |||
07b479d3bf | |||
9ec1a876d1 | |||
2a8ef46357 | |||
a3a5a19710 | |||
cf1a632e3e | |||
d8e801a178 | |||
df3d9c644f | |||
fb351a2e8d | |||
ad9a9e679f | |||
3a6fe46e26 | |||
6928c45106 | |||
057ca6edba | |||
3020a43ca2 | |||
3b36350faf | |||
759d7a1ccb | |||
c4bea59899 | |||
f680d0cefa | |||
e29cf10b03 | |||
b720c1224b | |||
44ae248e72 | |||
698f3f0329 | |||
fe2aba1e74 | |||
5c258c0b8b | |||
f47d06eded | |||
6e25befe64 | |||
b023e6bcba | |||
bbe295aea9 | |||
df4791a3b1 | |||
f363952d13 | |||
9b08a69426 | |||
4912d1f9e8 | |||
3b9343debf | |||
fab63e3eee | |||
7a178b29af | |||
937621ae7e | |||
f36a545c93 | |||
20b3218aab | |||
87138d7b1e | |||
c88a02c101 | |||
04eeda81c7 | |||
8afe3e0524 | |||
6e1039893d | |||
051903761c | |||
f7d9892205 | |||
e358a0d1a4 | |||
bf16d9d763 | |||
90aca411aa | |||
31ea1683aa | |||
6923776886 | |||
bcd6f3bf1a | |||
26bc3d7d61 | |||
084258ee6c | |||
b0dc51e14c | |||
e20bf87831 | |||
c68a84082f | |||
c9553bf7e5 | |||
35b2cd330c | |||
9ae12826a8 | |||
5df1659c6f | |||
a894b9eff5 | |||
e314f788e7 | |||
c3a29bef55 | |||
cfe496dcb7 | |||
d0c61e4847 | |||
20c220ffee | |||
20665dc119 | |||
0a3136a291 | |||
ffd7a943f4 | |||
a8ac5aa872 | |||
c99432ea52 | |||
ee7acd7c1b | |||
2c4b9a8546 | |||
c6a7db63d7 | |||
30be2871f2 | |||
1432f7e50d | |||
bb5d6b632e | |||
0b8d7d92ae | |||
8fe0e155d3 | |||
aaccd2356b |
225
.drone.yml
225
.drone.yml
@ -11,26 +11,32 @@ trigger:
|
||||
exclude: [push, pull_request]
|
||||
|
||||
steps:
|
||||
- name: fedora-hugo
|
||||
- name: alpine-hugo
|
||||
pull: always
|
||||
image: immawanderer/fedora-hugo:linux-amd64
|
||||
image: docker.io/immawanderer/alpine-hugo:hugo-v0.115.3
|
||||
commands:
|
||||
- uname -r
|
||||
- cat /etc/fedora-release
|
||||
- hugo version
|
||||
|
||||
- name: alpine-rsync
|
||||
pull: always
|
||||
image: immawanderer/alpine-rsync:latest
|
||||
image: docker.io/immawanderer/alpine-rsync:latest
|
||||
commands:
|
||||
- uname -r
|
||||
|
||||
- name: hadolint
|
||||
pull: always
|
||||
image: hadolint/hadolint:2.9.1-alpine
|
||||
image: docker.io/hadolint/hadolint:2.10.0-alpine
|
||||
commands:
|
||||
- uname -r
|
||||
- hadolint --version
|
||||
|
||||
- name: golang
|
||||
pull: always
|
||||
image: docker.io/library/golang:1.21.0-alpine3.18
|
||||
commands:
|
||||
- uname -r
|
||||
- go version
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@ -47,16 +53,65 @@ trigger:
|
||||
depends_on:
|
||||
- pull
|
||||
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
||||
steps:
|
||||
- name: hugo-extended
|
||||
pull: if-not-exists
|
||||
image: immawanderer/fedora-hugo:linux-amd64
|
||||
- name: submodules
|
||||
image: docker.io/alpine/git:v2.36.2
|
||||
depends_on: [clone]
|
||||
commands:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- git submodule update --recursive
|
||||
|
||||
- name: hugo-extended
|
||||
pull: always
|
||||
image: docker.io/immawanderer/alpine-hugo:hugo-v0.115.3
|
||||
depends_on: [submodules]
|
||||
commands:
|
||||
- hugo version
|
||||
- hugo --gc=true --minify
|
||||
|
||||
- name: go fmt
|
||||
image: docker.io/library/golang:1.21.0-alpine3.18
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- clone
|
||||
commands:
|
||||
- go fmt
|
||||
|
||||
- name: go vet
|
||||
image: docker.io/library/golang:1.21.--alpine3.18
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go fmt
|
||||
commands:
|
||||
- go vet
|
||||
|
||||
- name: go build
|
||||
pull: if-not-exists
|
||||
image: docker.io/library/golang:1.21.0-alpine3.18
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go vet
|
||||
# wait until the site is output into './public'.
|
||||
- hugo-extended
|
||||
environment:
|
||||
GOFLAGS: -trimpath -mod=readonly -modcacherw
|
||||
commands:
|
||||
- go build -v -ldflags "-s -w -X main.Version=${DRONE_COMMIT}" .
|
||||
|
||||
volumes:
|
||||
- name: gopath
|
||||
temp: {}
|
||||
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@ -75,14 +130,16 @@ depends_on:
|
||||
|
||||
steps:
|
||||
- name: hadolint
|
||||
image: hadolint/hadolint:v2.9.1-alpine
|
||||
image: docker.io/hadolint/hadolint:v2.10.0-alpine
|
||||
depends_on: [clone]
|
||||
commands:
|
||||
- hadolint --version
|
||||
- hadolint Dockerfile
|
||||
|
||||
- name: build
|
||||
- name: check compose
|
||||
pull: always
|
||||
image: tmaier/docker-compose:latest
|
||||
image: docker.io/tmaier/docker-compose:latest
|
||||
depends_on: [clone]
|
||||
volumes:
|
||||
- name: s
|
||||
path: /var/run/docker.sock
|
||||
@ -90,12 +147,25 @@ steps:
|
||||
COMPOSE_DOCKER_CLI_BUILD: 1
|
||||
DOCKER_BUILDKIT: 1
|
||||
commands:
|
||||
- docker-compose build --no-cache --pull
|
||||
- docker compose -f docker-compose.yml config -q
|
||||
|
||||
- name: build
|
||||
pull: always
|
||||
image: docker.io/tmaier/docker-compose:latest
|
||||
depends_on: [hadolint, check compose]
|
||||
volumes:
|
||||
- name: s
|
||||
path: /var/run/docker.sock
|
||||
environment:
|
||||
COMPOSE_DOCKER_CLI_BUILD: 1
|
||||
DOCKER_BUILDKIT: 1
|
||||
commands:
|
||||
- docker compose build --build-arg VCS_REF=${DRONE_COMMIT} --no-cache --pull
|
||||
|
||||
volumes:
|
||||
- name: s
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
path: /run/docker.sock
|
||||
|
||||
|
||||
---
|
||||
@ -117,18 +187,24 @@ depends_on:
|
||||
- build
|
||||
|
||||
steps:
|
||||
- name: hugo-extended
|
||||
pull: if-not-exists
|
||||
image: immawanderer/fedora-hugo:linux-amd64
|
||||
- name: submodules
|
||||
image: docker.io/alpine/git:v2.36.2
|
||||
depends_on: [clone]
|
||||
commands:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- git submodule update --recursive
|
||||
|
||||
- name: hugo-extended
|
||||
pull: always
|
||||
image: docker.io/immawanderer/alpine-hugo:hugo-v0.115.3
|
||||
depends_on: [submodules]
|
||||
commands:
|
||||
- hugo version
|
||||
- hugo --gc=true --minify
|
||||
|
||||
- name: deploy
|
||||
pull: if-not-exists
|
||||
image: alpine:3.15.0
|
||||
image: docker.io/library/alpine:3.15.0
|
||||
when:
|
||||
status:
|
||||
- success
|
||||
@ -178,57 +254,118 @@ node:
|
||||
depends_on:
|
||||
- build
|
||||
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
||||
steps:
|
||||
- name: hugo-extended
|
||||
pull: if-not-exists
|
||||
image: immawanderer/fedora-hugo:linux-amd64
|
||||
- name: submodules
|
||||
image: docker.io/alpine/git:v2.36.2
|
||||
depends_on: [clone]
|
||||
commands:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- git submodule update --recursive
|
||||
|
||||
- name: hugo-extended
|
||||
pull: always
|
||||
image: docker.io/immawanderer/alpine-hugo:hugo-v0.115.3
|
||||
depends_on: [submodules]
|
||||
commands:
|
||||
- hugo version
|
||||
- hugo --gc=true --minify
|
||||
|
||||
- name: rm-intermediate
|
||||
pull: if-not-exists
|
||||
image: immawanderer/fedora-hugo:linux-amd64
|
||||
depends_on:
|
||||
- hugo-extended
|
||||
commands:
|
||||
- rm -rf ./public
|
||||
|
||||
- name: hadolint
|
||||
image: hadolint/hadolint:v2.9.1-alpine
|
||||
image: docker.io/hadolint/hadolint:v2.10.0-alpine
|
||||
depends_on:
|
||||
- clone
|
||||
commands:
|
||||
- hadolint --version
|
||||
- hadolint Dockerfile
|
||||
|
||||
- name: check compose
|
||||
pull: always
|
||||
image: docker.io/tmaier/docker-compose:latest
|
||||
depends_on: [clone]
|
||||
volumes:
|
||||
- name: s
|
||||
path: /var/run/docker.sock
|
||||
environment:
|
||||
COMPOSE_DOCKER_CLI_BUILD: 1
|
||||
DOCKER_BUILDKIT: 1
|
||||
commands:
|
||||
- docker compose -f docker-compose.yml config -q
|
||||
|
||||
- name: go fmt
|
||||
image: docker.io/library/golang:1.21.0-alpine3.18
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- clone
|
||||
commands:
|
||||
- go fmt
|
||||
|
||||
- name: go vet
|
||||
image: docker.io/library/golang:1.21.0-alpine3.18
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go fmt
|
||||
# wait until the site is output into './public'.
|
||||
- hugo-extended
|
||||
commands:
|
||||
- go vet
|
||||
|
||||
- name: go build
|
||||
image: docker.io/library/golang:1.21.0-alpine3.18
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
||||
depends_on:
|
||||
- go vet
|
||||
commands:
|
||||
- go build -v -ldflags "-s -w -X main.Version=${DRONE_COMMIT}" .
|
||||
|
||||
- name: rm-intermediate
|
||||
pull: if-not-exists
|
||||
image: docker.io/immawanderer/fedora-hugo:linux-amd64
|
||||
depends_on:
|
||||
- go build
|
||||
commands:
|
||||
- rm -rf ./public
|
||||
|
||||
- name: build
|
||||
pull: always
|
||||
image: tmaier/docker-compose:latest
|
||||
image: docker.io/tmaier/docker-compose:latest
|
||||
depends_on:
|
||||
- rm-intermediate
|
||||
- hadolint
|
||||
- check compose
|
||||
- go fmt
|
||||
- go vet
|
||||
- go build
|
||||
volumes:
|
||||
- name: s
|
||||
path: /var/run/docker.sock
|
||||
commands:
|
||||
- docker-compose build --no-cache
|
||||
- docker compose build --build-arg VCS_REF=${DRONE_COMMIT} --no-cache
|
||||
when:
|
||||
branch: master
|
||||
status: success
|
||||
|
||||
- name: deploy
|
||||
pull: always
|
||||
image: tmaier/docker-compose:latest
|
||||
image: docker.io/tmaier/docker-compose:latest
|
||||
depends_on:
|
||||
- build
|
||||
volumes:
|
||||
- name: s
|
||||
path: /var/run/docker.sock
|
||||
commands:
|
||||
- docker-compose -p ${DRONE_REPO_NAME} up -d --remove-orphans --scale homepage=4
|
||||
- docker compose -p ${DRONE_REPO_NAME} up
|
||||
-d
|
||||
--remove-orphans
|
||||
--scale homepage=1
|
||||
when:
|
||||
branch: master
|
||||
status: success
|
||||
@ -236,7 +373,9 @@ steps:
|
||||
volumes:
|
||||
- name: s
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
path: /run/docker.sock
|
||||
- name: gopath
|
||||
temp: {}
|
||||
|
||||
|
||||
---
|
||||
@ -266,7 +405,7 @@ depends_on: [deploy, deploy-staging]
|
||||
steps:
|
||||
- name: discord
|
||||
pull: if-not-exists
|
||||
image: appleboy/drone-discord:latest
|
||||
image: docker.io/appleboy/drone-discord:latest
|
||||
settings:
|
||||
message: >
|
||||
{{#success build.status}}
|
||||
@ -306,7 +445,7 @@ depends_on: [deploy]
|
||||
steps:
|
||||
- name: discord
|
||||
pull: always
|
||||
image: appleboy/drone-discord:latest
|
||||
image: docker.io/appleboy/drone-discord:latest
|
||||
settings:
|
||||
message: >
|
||||
{{#success build.status}}
|
||||
@ -324,3 +463,9 @@ steps:
|
||||
from_secret: discord_webhook_hourly_id
|
||||
webhook_token:
|
||||
from_secret: discord_webhook_hourly_token
|
||||
|
||||
---
|
||||
kind: signature
|
||||
hmac: 4e178bb873563499a7b3b00fdb372acc239dedfb8b151858598a29778349f44c
|
||||
|
||||
...
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,3 +2,6 @@
|
||||
public/
|
||||
resources/
|
||||
*.swp
|
||||
|
||||
# go binary
|
||||
homepage
|
||||
|
96
.golangci.yml
Normal file
96
.golangci.yml
Normal file
@ -0,0 +1,96 @@
|
||||
---
|
||||
run:
|
||||
go: '1.20'
|
||||
tests: true
|
||||
skip-dirs:
|
||||
- static
|
||||
- public
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bidichk
|
||||
- dupl
|
||||
- decorder
|
||||
- dogsled
|
||||
- exportloopref
|
||||
- forbidigo
|
||||
- gas
|
||||
- gocognit
|
||||
- goconst
|
||||
- gocritic
|
||||
- godot
|
||||
- govet
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- ineffassign
|
||||
- misspell
|
||||
# - prealloc
|
||||
- revive
|
||||
- tparallel
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- wastedassign
|
||||
- whitespace
|
||||
- wsl
|
||||
|
||||
linter-settings:
|
||||
dupl:
|
||||
threshold: 100
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- experimental
|
||||
- opinionated
|
||||
- performance
|
||||
- style
|
||||
disabled-checks:
|
||||
- dupImport # https://github.com/go-critic/go-critic/issues/845
|
||||
- ifElseChain
|
||||
- octalLiteral
|
||||
- whyNoLint
|
||||
- wrapperFunc
|
||||
gocyclo:
|
||||
min-complexity: 15
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
lang-version: "1.20"
|
||||
govet:
|
||||
check-shadowing: true
|
||||
revive:
|
||||
severity: warning
|
||||
confidence: 0.8
|
||||
errorCode: 1
|
||||
warningCode: 1
|
||||
rules:
|
||||
- name: blank-imports
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: error-naming
|
||||
- name: exported
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: var-naming
|
||||
- name: var-declaration
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: time-naming
|
||||
- name: unexported-return
|
||||
- name: indent-error-flow
|
||||
- name: errorf
|
||||
- name: duplicated-imports
|
||||
- name: modifies-value-receiver
|
||||
wsl:
|
||||
allow-cuddle-declaration: true
|
||||
...
|
@ -1,3 +1,4 @@
|
||||
---
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
@ -6,3 +7,41 @@ repos:
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
exclude: .drone.yml # drone's yaml is somewhat strange sometimes
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: hugo-version-check
|
||||
name: hugo version check
|
||||
entry: |
|
||||
bash -c "
|
||||
files='.drone.yml Dockerfile'
|
||||
count=$(grep -oE '(hugo-v)[0-9].[0-9].[0-9].[0-9]' $files | cut -d':' -f2 | sed -e 's/^ *//g' -e 's/hugo-v//g' | uniq | wc -l)
|
||||
if [ $count -gt 1 ]; then
|
||||
echo hugo versions inconsistent:
|
||||
grep -noE --color=always '(hugo-v)[0-9].[0-9].[0-9].[0-9]' $files
|
||||
exit 1
|
||||
fi
|
||||
"
|
||||
language: system
|
||||
pass_filenames: false
|
||||
- id: check-compose-file
|
||||
name: check compose file
|
||||
language: system
|
||||
entry: docker-compose -f docker-compose.yml config
|
||||
pass_filenames: false
|
||||
- id: yamllint
|
||||
name: yamllint
|
||||
language: system
|
||||
entry: yamllint .
|
||||
pass_filenames: false
|
||||
- repo: https://git.dotya.ml/wanderer/hadolint-pre-commit
|
||||
rev: v0.0.1
|
||||
hooks:
|
||||
- id: hadolint-container
|
||||
- repo: https://github.com/dnephin/pre-commit-golang
|
||||
rev: v0.5.0
|
||||
hooks:
|
||||
- id: go-mod-tidy
|
||||
- id: go-unit-tests
|
||||
- id: golangci-lint
|
||||
- id: go-build
|
||||
...
|
||||
|
13
.yamllint
Normal file
13
.yamllint
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
|
||||
yaml-files:
|
||||
- '*.yaml'
|
||||
- '*.yml'
|
||||
- '.yamllint'
|
||||
|
||||
rules:
|
||||
line-length:
|
||||
level: warning
|
||||
|
||||
# vim: ft=yaml bs=2 ts=2
|
||||
...
|
52
Dockerfile
52
Dockerfile
@ -1,28 +1,36 @@
|
||||
FROM immawanderer/fedora-hugo:linux-amd64 AS hugobuild
|
||||
RUN mkdir -pv /homepage
|
||||
COPY . /homepage
|
||||
# syntax=docker/dockerfile-upstream:master-labs
|
||||
# refs:
|
||||
# https://docs.docker.com/develop/develop-images/build_enhancements/#overriding-default-frontends
|
||||
# https://pythonspeed.com/articles/docker-buildkit/
|
||||
FROM docker.io/alpine/git:v2.36.2 AS submodules
|
||||
|
||||
WORKDIR /homepage
|
||||
|
||||
RUN git submodule init \
|
||||
&& git submodule update --recursive \
|
||||
&& hugo version
|
||||
# "DL3059 info: Multiple consecutive `RUN` instructions.
|
||||
# Consider consolidation."
|
||||
# hadolint ignore=DL3059
|
||||
RUN hugo --minify --gc=true
|
||||
COPY . .
|
||||
|
||||
WORKDIR /
|
||||
RUN git submodule init && \
|
||||
git submodule update --recursive
|
||||
|
||||
FROM nginx:mainline-alpine
|
||||
COPY --from=hugobuild /homepage/public/ /usr/share/nginx/html
|
||||
FROM docker.io/immawanderer/alpine-hugo:hugo-v0.115.3 AS hugobuild
|
||||
|
||||
# tripple slash reference
|
||||
# https://stackoverflow.com/questions/5190966/using-sed-to-insert-tabs/5191165#5191165
|
||||
RUN sed -i -e 's/^worker_processes auto;/worker_processes auto;/'\
|
||||
-e "/^events {$/ a \\\tmulti_accept on;\n\tuse epoll;"\
|
||||
-e "/^http {$/ a \\\tserver_tokens off;\n\tetag off;\n"\
|
||||
-e 's/#tcp_nopush/tcp_nopush/'\
|
||||
-e "/tcp_nopush/ a \\\ttcp_nodelay on;"\
|
||||
-e "s/^ */$(printf '\t')/"\
|
||||
/etc/nginx/nginx.conf
|
||||
COPY --from=submodules /homepage/ /homepage/
|
||||
|
||||
WORKDIR /homepage
|
||||
|
||||
RUN hugo version && \
|
||||
hugo --minify --gc=true --cleanDestinationDir
|
||||
|
||||
FROM docker.io/library/golang:1.21.0-alpine3.18 AS gobuild
|
||||
COPY --from=hugobuild /homepage/ /homepage/
|
||||
|
||||
WORKDIR /homepage
|
||||
|
||||
ARG VCS_REF=development
|
||||
|
||||
RUN CGO_ENABLED=0 GOFLAGS='-trimpath -mod=readonly -modcacherw' \
|
||||
go build -o homepage-app -v -ldflags "-s -w -X main.version=$VCS_REF" .
|
||||
|
||||
FROM scratch
|
||||
COPY --from=gobuild /homepage/homepage-app /homepage
|
||||
|
||||
ENTRYPOINT ["/homepage"]
|
||||
|
@ -1,5 +1,6 @@
|
||||
# dotya.ml
|
||||
# [dotya.ml](https://git.dotya.ml/dotya.ml/homepage/)
|
||||
|
||||
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
|
||||
[![Build Status](https://drone.dotya.ml/api/badges/dotya.ml/homepage/status.svg?ref=refs/heads/master)](https://drone.dotya.ml/dotya.ml/homepage)
|
||||
[![Mozilla HTTP Observatory Grade](https://img.shields.io/mozilla-observatory/grade-score/dotya.ml)](https://observatory.mozilla.org/analyze/dotya.ml)
|
||||
[![Security Headers](https://img.shields.io/security-headers?url=https%3A%2F%2Fdotya.ml)](https://securityheaders.com/?q=https%3A%2F%2Fdotya.ml)
|
||||
|
@ -1,6 +1,8 @@
|
||||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
lastmod: {{ .Date }}
|
||||
enableGitInfo: true
|
||||
draft: true
|
||||
---
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
// Colors
|
||||
//
|
||||
$theme: #D8D8D8;
|
||||
$text: #D8D8D8;
|
||||
$light-grey: #282a2b; // Background
|
||||
$dark-grey: #282a2b; // Hover Bar
|
||||
$highlight-grey: #151718; // Highlight background of `keyword`
|
||||
$midnightblue: #151718; // Code Background
|
||||
$theme: #613583; // hyperlink highlight background colour, .post-info
|
||||
// site-local link :hover highlight colour
|
||||
$text: #21fa45; // colour of normal text
|
||||
$light-grey: #010000; // background
|
||||
$dark-grey: #111115; // hover bar
|
||||
$highlight-grey: #9141ac; // code (not in pre) background
|
||||
$midnightblue: #151718; // code text (not in pre) colour
|
||||
|
||||
// Fonts
|
||||
//
|
||||
|
@ -48,19 +48,20 @@ pre {
|
||||
letter-spacing: normal;
|
||||
white-space: pre;
|
||||
color: #eee;
|
||||
background: $midnightblue;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
border-radius: 5px;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
|
||||
code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: $midnightblue;
|
||||
color: #eee;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
color: #eee;
|
||||
color: $midnightblue;
|
||||
background: $highlight-grey;
|
||||
border-radius: 3px;
|
||||
padding: 0 3px;
|
||||
@ -94,8 +95,7 @@ a {
|
||||
transition-timing-function: ease-out;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
text-shadow: 0 0 1px #fff;
|
||||
color: $highlight-grey;
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,6 +380,7 @@ p.img-404 {
|
||||
|
||||
&:hover {
|
||||
border-color: #fff;
|
||||
color: $highlight-grey;
|
||||
}
|
||||
|
||||
svg {
|
||||
|
64
config.toml
64
config.toml
@ -6,6 +6,7 @@ enableGitInfo = true
|
||||
|
||||
pygmentsCodefences = true
|
||||
pygmentsUseClasses = true
|
||||
pygmentsStyle = "fruity"
|
||||
enableEmoji = true
|
||||
|
||||
[author]
|
||||
@ -14,11 +15,14 @@ enableEmoji = true
|
||||
[taxonomies]
|
||||
tag = 'tags'
|
||||
|
||||
[permalinks]
|
||||
posts = '/:year/:month/:title/'
|
||||
|
||||
[params]
|
||||
dateform = "Jan 2, 2006"
|
||||
dateformShort = "Jan 2"
|
||||
dateformNum = "2006-02-01"
|
||||
dateformNumTime = "2006-02-01T15:04+00:00"
|
||||
dateform = "02 Jan 2006"
|
||||
dateformShort = "02 Jan"
|
||||
dateformNum = "02 Jan 2006"
|
||||
dateformNumTime = "Mon, 02 Jan 2006 15:04:05 -0700"
|
||||
# Metadata mostly used in document's head
|
||||
description = "dotya.ml homepage"
|
||||
keywords = "homepage, development, git, programming"
|
||||
@ -56,36 +60,38 @@ enableEmoji = true
|
||||
alt = "dockerhub profile page"
|
||||
|
||||
[languages]
|
||||
[languages.logo.params.en]
|
||||
logoText = "dotya.ml"
|
||||
logoHomeLink = "/"
|
||||
|
||||
[languages.en]
|
||||
title = "dotya.ml"
|
||||
subtitle = ""
|
||||
|
||||
[languages.en.params]
|
||||
keywords = "homepage, development, git, programming"
|
||||
subtitle = "hello friend. hello friend? that's lame. maybe I should give you a name."
|
||||
readOtherPosts = ""
|
||||
|
||||
[languages.en.params.logo]
|
||||
logoText = "dotya.ml"
|
||||
logoHomeLink = "/"
|
||||
|
||||
# You can create a language based menu
|
||||
[languages.en.menu]
|
||||
[[languages.en.menu.main]]
|
||||
identifier = "about"
|
||||
name = "about"
|
||||
url = "/about/"
|
||||
alt = "dotya.ml status"
|
||||
weight = 1
|
||||
[[languages.en.menu.main]]
|
||||
identifier = "posts"
|
||||
name = "posts"
|
||||
url = "/posts/"
|
||||
alt = "dotya.ml posts"
|
||||
weight = 2
|
||||
[[languages.en.menu.main]]
|
||||
identifier = "contact"
|
||||
name = "contact"
|
||||
url = "/contact/"
|
||||
alt = "dotya.ml contact"
|
||||
weight = 3
|
||||
# You can create a language based menu
|
||||
[languages.en.menu]
|
||||
[[languages.en.menu.main]]
|
||||
identifier = "about"
|
||||
name = "about"
|
||||
url = "/about/"
|
||||
alt = "about dotya.ml"
|
||||
weight = 1
|
||||
[[languages.en.menu.main]]
|
||||
identifier = "posts"
|
||||
name = "posts"
|
||||
url = "/posts/"
|
||||
alt = "dotya.ml posts"
|
||||
weight = 2
|
||||
[[languages.en.menu.main]]
|
||||
identifier = "contact"
|
||||
name = "contact"
|
||||
url = "/contact/"
|
||||
alt = "dotya.ml contact"
|
||||
weight = 3
|
||||
|
||||
[privacy]
|
||||
[privacy.disqus]
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
title: "0x28bd2388"
|
||||
description: "instructions on how to verify 0x28bd2388 gpg key"
|
||||
date: 2020-03-07T16:22:03+01:00
|
||||
draft: false
|
||||
---
|
||||
|
@ -1,49 +1,29 @@
|
||||
---
|
||||
title: "about dotya.ml"
|
||||
description: "an overview of dotya.ml's activities and mission"
|
||||
date: 2020-08-06T17:15:03+01:00
|
||||
lastmod: 2022-09-06T16:11:32+02:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
Free services provided for fun as a hobby with passion and :white_heart:\
|
||||
So far we have:
|
||||
* [Gitea](https://gitea.io) SCM instance at https://git.dotya.ml
|
||||
* [DroneCI](https://drone.io) instance (login with a Gitea account) at https://drone.dotya.ml
|
||||
* [DNSCrypt](https://dnscrypt.info/) server
|
||||
Free services provided for fun as a hobby with passion and :white_heart:
|
||||
|
||||
### Clearnet services
|
||||
see what we have so far: [list of services]({{< relref "services.md" >}}).
|
||||
|
||||
### Onion services
|
||||
> Note: This is a work in progress - more services are to come
|
||||
|
||||
Gitea: http://2crftbzxbcoqolvzreaaeyrod5qwycayef55gxgzgfcpqlaxrnh3kkqd.onion\
|
||||
this site: http://6426tqrh4y5uobmo5y2csaip3m3avmjegd2kpa24sadekpxglbm34aqd.onion\
|
||||
prometheus: http://vognfwm7c6wq2gxqcmswi2flwckuxryefd7n3axxkvlpasdjhns5buqd.onion\
|
||||
grafana: http://6t3ydf7sl7iso2wbymbfjtaq6qqlrms37ffik2siulsljc3ubobklnid.onion\
|
||||
statuspage: http://o4irro4dspyuytbw2b2g2ac4ukkh2ex53oolhzw7hrfjmq6tiklrtwqd.onion
|
||||
|
||||
#### current progress on onion drone
|
||||
https://git.dotya.ml/dotya.ml/community/issues/5
|
||||
|
||||
Making `DroneCI` available as a hidden service would require either
|
||||
a) spinning up another instance, for which we currently don't have capacities, or
|
||||
b) some kind of an evil hack that we've not yet discovered.\
|
||||
We're open to ideas - if you know how to make this work, please, send us a patch,
|
||||
PR or an email with anything interesting and worthwile.
|
||||
|
||||
set-up-but-not-properly-working drone: http://c3vqfx2dqltvdbsqu3ndqwcxsp3uk3vcxo2jsigie5zfajub3j3y35id.onion
|
||||
|
||||
### DNS(Crypt)
|
||||
a non-logging name server, securing connections using DNSCrypt for increased
|
||||
privacy, that is - as long as we trust our own server.
|
||||
|
||||
see [DNSCrypt](/posts/dnscrypt/) for more.
|
||||
for increased privacy of our users, *some* services are also available
|
||||
natively via [TOR](https://www.torproject.org/), have a look at
|
||||
[onions 🧅]({{< relref "onions.md" >}}) for details.
|
||||
|
||||
### Observability
|
||||
long-term monitoring of trends for services we're running
|
||||
to enable long-term monitoring of trends for services we're running:
|
||||
* [prometheus](https://prometheus.io) at https://metrics.dotya.ml
|
||||
* [grafana](https://grafana.com) at https://grafana.dotya.ml
|
||||
|
||||
### Status
|
||||
* in-house status monitor at https://status.dotya.ml
|
||||
* UptimeRobot hosted dashboard at https://stats.uptimerobot.com/93yPqFmmx8
|
||||
* in-house status monitor at https://status.dotya.ml (courtesy of [statping-ng](https://statping-ng.github.io))
|
||||
* UptimeRobot ([affiliate link](https://uptimerobot.com/?rid=a60f8392870bc9)) hosted dashboard at https://stats.uptimerobot.com/93yPqFmmx8
|
||||
|
||||
### Security
|
||||
[HSTS](https://tools.ietf.org/rfc/rfc6797.txt) has been enabled early on for `dotya.ml`,
|
||||
@ -59,3 +39,9 @@ Scoring 130 out of 100 points
|
||||
* [SecurityHeaders](https://securityheaders.com/) report at https://securityheaders.com/?q=https%3A%2F%2Fdotya.ml
|
||||
|
||||
* SSL Labs [TLS rating](https://www.ssllabs.com/ssltest/analyze.html?d=dotya.ml): *A+*
|
||||
|
||||
* [cryptcheck.fr](https://cryptcheck.fr/https/dotya.ml): *A+*
|
||||
|
||||
### Privacy
|
||||
see [privacy]({{< relref "privacy" >}}), the short version being *we are not
|
||||
selling you out* 🎉.
|
||||
|
@ -1,27 +1,31 @@
|
||||
---
|
||||
title: "contact"
|
||||
description: "ways to get in contact with dotya.ml maintainers"
|
||||
date: 2020-03-07T01:53:03+01:00
|
||||
draft: false
|
||||
---
|
||||
\-- wanderer
|
||||
|
||||
## \-- wanderer
|
||||
```bash
|
||||
echo a_mirre.utb.cz | sed 's/\./@/'
|
||||
echo wanderer+hello.dotya.ml | sed 's/\./@/'
|
||||
```
|
||||
|
||||
fingerprint:
|
||||
use [age](https://github.com/FiloSottile/age) if possible.\
|
||||
pubkey:
|
||||
```sh
|
||||
age16xdcxvnnhcekv59ncj5fmdarhm8csdgd9nk7nzxpywg5xtehq4kq49880e
|
||||
```
|
||||
|
||||
gpg fingerprint:
|
||||
|
||||
```bash
|
||||
E860 AB3C D007 8D30 E86C DA74 7B28 D8DC 28BD 2388
|
||||
```
|
||||
|
||||
the corresponding pubkey: [0x28bd2388](/28bd2388/)
|
||||
the corresponding pubkey: [0x28bd2388]({{< relref "28bd2388.md" >}})
|
||||
plain key file: [0x28bd2388.asc](/store/0x28bd2388.asc)
|
||||
openpgp key server link: [0x28bd2388](https://keys.openpgp.org/vks/v1/by-fingerprint/E860AB3CD0078D30E86CDA747B28D8DC28BD2388)
|
||||
|
||||
\
|
||||
\-- 2EEEB
|
||||
|
||||
## \-- 2EEEB
|
||||
```bash
|
||||
echo andrej.pillar,vutbr.cz | sed 's/\,/@/'
|
||||
```
|
||||
@ -35,21 +39,12 @@ the pubkey can be found in a [key repo](https://keyserver.ubuntu.com/pks/lookup?
|
||||
|
||||
communication using gpg is *preferable*
|
||||
|
||||
## privacy
|
||||
|
||||
### tl;dr
|
||||
[Access logs](https://en.wikipedia.org/wiki/Server_log) are stored for up to 30 days for the purpose of defending against abuse.
|
||||
|
||||
### the long version
|
||||
Since I don't like such practices myself, this site *does not* collect
|
||||
*any* kind of user/browser/device/user agent/network identifier,
|
||||
which - for simplicity's sake is - no data at all - **FOR PROFIT**.\
|
||||
Period.
|
||||
|
||||
No personally identifiable data is collected - actively or passively - and therefore can't be passed on to third parties (such as advertisement companies), nor is there any intention of *ever* doing so.
|
||||
|
||||
Visitor device's apparent IP address *is stored* in access log, along with a [user agent](https://duckduckgo.com/?t=ffab&q=user+agent) string, which allows us to defend against abuse.
|
||||
These logs are automatically overwriten approximately every 30 days.
|
||||
## Privacy
|
||||
see [privacy]({{< relref "about#privacy" >}}), or in case of questions, say
|
||||
hi and ask away at:
|
||||
```sh
|
||||
hello at dotya dot ml
|
||||
```
|
||||
|
||||
## Long live the libre world!
|
||||
|
||||
|
42
content/onions.md
Normal file
42
content/onions.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
title: "onions 🧅"
|
||||
description: "summary of onion services dotya.ml provides - a more anonymous way to access your stuff"
|
||||
date: 2022-08-30T12:00:42+02:00
|
||||
lastmod: 2022-08-30T12:00:42+02:00
|
||||
enableGitInfo: true
|
||||
draft: false
|
||||
---
|
||||
|
||||
> Note: This is a work in progress - more services are to come
|
||||
|
||||
> Note 2: the `http` part of the links below is misleading, as (our) [onion
|
||||
> services](https://community.torproject.org/onion-services/) are in fact
|
||||
> fully encrypted every step of the way using `https`, only the certs are not
|
||||
> signed by a conventional CA (certificate authority), which means
|
||||
> conventional browsers (including Firefox-based TorBrowser) would cry if the
|
||||
> sites were served with explicit `https` prefix.
|
||||
> this decreases the security by exactly zero and unless LetsEncrypt starts
|
||||
> issuing certs for `.onion` domains, we're not going to see broad usage of
|
||||
> *explicit* `https` prefix on onion services, since only the likes of NY
|
||||
> Times, BBC, Twitter or Facebook are going to make their CAs to sign them a
|
||||
> neat little `.onion` cert.
|
||||
|
||||
Gitea: http://2crftbzxbcoqolvzreaaeyrod5qwycayef55gxgzgfcpqlaxrnh3kkqd.onion\
|
||||
this site: http://6426tqrh4y5uobmo5y2csaip3m3avmjegd2kpa24sadekpxglbm34aqd.onion\
|
||||
prometheus: http://vognfwm7c6wq2gxqcmswi2flwckuxryefd7n3axxkvlpasdjhns5buqd.onion\
|
||||
grafana: http://6t3ydf7sl7iso2wbymbfjtaq6qqlrms37ffik2siulsljc3ubobklnid.onion\
|
||||
statuspage: http://o4irro4dspyuytbw2b2g2ac4ukkh2ex53oolhzw7hrfjmq6tiklrtwqd.onion
|
||||
|
||||
#### current progress on onion drone
|
||||
https://git.dotya.ml/dotya.ml/community/issues/5
|
||||
|
||||
Making `DroneCI` available as a hidden service would require either
|
||||
a) spinning up another instance, for which we currently don't have capacities, or
|
||||
b) some kind of an evil hack that we've not yet discovered.\
|
||||
We're open to ideas - if you know how to make this work, please, send us a patch,
|
||||
PR or an email with anything interesting and worthwile.
|
||||
|
||||
set-up-but-not-properly-working drone: http://c3vqfx2dqltvdbsqu3ndqwcxsp3uk3vcxo2jsigie5zfajub3j3y35id.onion
|
||||
|
||||
### clearnet
|
||||
also check out [services]({{< relref "services" >}})...
|
@ -1,45 +1,118 @@
|
||||
---
|
||||
title: "DNSCrypt"
|
||||
title: "DNSCrypt - running the server"
|
||||
description: "How we run a DNSCrypt server using docker-compose"
|
||||
date: 2021-08-06T23:38:45+02:00
|
||||
author: wanderer - https://git.dotya.ml/wanderer
|
||||
draft: false
|
||||
toc: true
|
||||
enableGitInfo: true
|
||||
tags: [dnscrypt, dns, privacy, security, censorship]
|
||||
---
|
||||
|
||||
### why are you doing this?
|
||||
## why are you doing this?
|
||||
There are many publicly available [open resolvers using DoT, DoH or
|
||||
DNSCrypt](https://dnscrypt.info/public-servers) to secure the traffic. However,
|
||||
we have still felt the need to run our own, especially since it's such a
|
||||
critical part of the infrastructure. Since now it's a reality, we're offering
|
||||
it for public use.
|
||||
DNSCrypt](https://dnscrypt.info/public-servers) just sitting around the
|
||||
interwebs, waiting to secure the DNS traffic and protect it from whoever is
|
||||
looking.
|
||||
|
||||
### so what is it?
|
||||
However, we have still felt the need to run our own, especially since
|
||||
DNS is such a critical piece of infrastructure.
|
||||
|
||||
And now we're offering it for public use.
|
||||
|
||||
## so what is it?
|
||||
What we're running is a non-censoring, non-logging, DNSSEC-capable, DNSCrypt-enabled DNS
|
||||
resolver using
|
||||
[dnscrypt-server-docker](https://github.com/dnscrypt/dnscrypt-server-docker) project.
|
||||
Our resolver is available over both IPv4 and IPv6.
|
||||
Of course, our resolver is available over both IPv4 and IPv6.
|
||||
|
||||
### can I haz some plz
|
||||
> Since the name servers are not (yet) a part of any listing of public
|
||||
> resolvers, entries have to be added manually.
|
||||
## can I haz some plz
|
||||
Yes! As a matter of fact, you should even be able to get records on
|
||||
[OpenNIC](https://www.opennic.org/) domains.
|
||||
|
||||
You can try some using the awesome tool [`doggo`](https://github.com/mr-karan/doggo), like so:
|
||||
```shell
|
||||
doggo --debug --json NS epic. @sdns://AQcAAAAAAAAAETE0NC45MS43MC42Mjo1NDQzIHF-JiN46cNwFXJleEVWGWgrhe2QeysUtZoo9HwzYCMzITIuZG5zY3J5cHQtY2VydC5kbnNjcnlwdC5kb3R5YS5tbA
|
||||
```
|
||||
example response:
|
||||
```shell
|
||||
DEBUG[2022-09-01T00:22:23+02:00] initiating DNSCrypt resolver
|
||||
|
||||
DEBUG[2022-09-01T00:22:23+02:00] Starting doggo 🐶
|
||||
|
||||
DEBUG[2022-09-01T00:22:23+02:00] Attempting to resolve domain=epic. nameserver="144.91.70.62:5443" ndots=0
|
||||
[
|
||||
{
|
||||
"answers": [
|
||||
{
|
||||
"name": "epic.",
|
||||
"type": "NS",
|
||||
"class": "IN",
|
||||
"ttl": "86400s",
|
||||
"address": "ns13.opennic.glue.",
|
||||
"status": "",
|
||||
"rtt": "45ms",
|
||||
"nameserver": "144.91.70.62:5443"
|
||||
}
|
||||
],
|
||||
"authorities": null,
|
||||
"questions": [
|
||||
{
|
||||
"name": "epic.",
|
||||
"type": "NS",
|
||||
"class": "IN"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### `dnscrypt-proxy` configuration tips
|
||||
If you'd, for some reason, like to use exclusively our name servers, simply set
|
||||
the `server_names` in the root section of your `dnscrypt-proxy.toml` config
|
||||
file:
|
||||
```toml
|
||||
server_names = ['dotya.ml', 'dotya.ml-ipv6']
|
||||
```
|
||||
|
||||
By default servers are picked based on latency, which is a sane default and it
|
||||
is in fact what we use.
|
||||
|
||||
If in need of more granular nameserver selection based on anything other than
|
||||
latency they can additionally easily be filtered (without being explicitly
|
||||
listed) based on:
|
||||
* logging
|
||||
* filtering
|
||||
* DNSSEC capabilities
|
||||
* DoH, ODoH or DNSCrypt capabilities
|
||||
* IPv4 or IPv6 availability
|
||||
|
||||
Further, we also remove certain players from the equation by simply listing
|
||||
them in `disabled_server_names`, like so:
|
||||
```toml
|
||||
disabled_server_names = ['google-ipv6', 'cloudflare', 'cloudflare-ipv6', 'cisco', 'cisco-ipv6', 'cisco-familyshield', 'cisco-familyshield-ipv6', 'yandex', 'apple', 'doh.dns.apple.com']
|
||||
```
|
||||
|
||||
### old news
|
||||
> Update 2022-09-01: the servers are now a part of the official listing at
|
||||
> https://dnscrypt.info/public-servers/, so there is no point in adding them
|
||||
> manually anymore. Keeping this for posterity.
|
||||
|
||||
Paste one or both of the following entries in the `[static]` section of your
|
||||
`dnscrypt-proxy.toml` configuration file.
|
||||
|
||||
IPv4 (`144.91.70.62`)
|
||||
```toml
|
||||
[static. 'dnscrypt.dotya.ml-ipv4']
|
||||
stamp = 'sdns://AQcAAAAAAAAAETE0NC45MS43MC42Mjo1NDQzIHF-JiN46cNwFXJleEVWGWgrhe2QeysUtZoo9HwzYCMzITIuZG5zY3J5cHQtY2VydC5kbnNjcnlwdC5kb3R5YS5tbA'
|
||||
[static]
|
||||
# IPv4 (144.91.70.62, port 5443)
|
||||
[static. 'dnscrypt.dotya.ml-ipv4']
|
||||
stamp = 'sdns://AQcAAAAAAAAAETE0NC45MS43MC42Mjo1NDQzIHF-JiN46cNwFXJleEVWGWgrhe2QeysUtZoo9HwzYCMzITIuZG5zY3J5cHQtY2VydC5kbnNjcnlwdC5kb3R5YS5tbA'
|
||||
|
||||
# IPv6 (2a02:c207:2030:396::1, port 5443)
|
||||
[static. 'dnscrypt.dotya.ml-ipv6']
|
||||
stamp = 'sdns://AQcAAAAAAAAAHFsyYTAyOmMyMDc6MjAzMDozOTY6OjFdOjU0NDMgcX4mI3jpw3AVcmV4RVYZaCuF7ZB7KxS1mij0fDNgIzMhMi5kbnNjcnlwdC1jZXJ0LmRuc2NyeXB0LmRvdHlhLm1s'
|
||||
```
|
||||
|
||||
IPv6 (`2a02:c207:2030:396::1`)
|
||||
```toml
|
||||
[static. 'dnscrypt.dotya.ml-ipv6']
|
||||
stamp = 'sdns://AQcAAAAAAAAAHFsyYTAyOmMyMDc6MjAzMDozOTY6OjFdOjU0NDMgcX4mI3jpw3AVcmV4RVYZaCuF7ZB7KxS1mij0fDNgIzMhMi5kbnNjcnlwdC1jZXJ0LmRuc2NyeXB0LmRvdHlhLm1s'
|
||||
```
|
||||
|
||||
### Configuration
|
||||
## server configuration
|
||||
Files used to set up and run this service can be found here:\
|
||||
https://git.dotya.ml/dotya.ml/dnscrypt-server.
|
||||
It's a `docker-compose` setup managed with `systemd`, similar to how Drone CI
|
||||
|
157
content/posts/m32.md
Normal file
157
content/posts/m32.md
Normal file
@ -0,0 +1,157 @@
|
||||
---
|
||||
title: "Compiling C programs using -m32 on Arch in 2023"
|
||||
description: "Compiling C programs for 32bit on Arch in 2023"
|
||||
date: 2023-06-14T12:32:52+02:00
|
||||
author: wanderer - https://git.dotya.ml/wanderer
|
||||
draft: false
|
||||
toc: true
|
||||
enableGitInfo: true
|
||||
images:
|
||||
tags:
|
||||
- archlinux
|
||||
- compilation
|
||||
- 32bit
|
||||
---
|
||||
|
||||
## Intro
|
||||
|
||||
> **Preliminary:** To be clear, this short post is not primarily concerned with
|
||||
> *running* the 32bit programs, instead specifically *compiling C programs for
|
||||
> 32bit (x86)*.
|
||||
|
||||
Compiling a `C` program for a 32bit architecture in 2023?
|
||||
|
||||
Well, one might still want to poke at reversing smaller address-space programs,
|
||||
*even in 2023*, and contrary to the popular belief, there still exist pieces of
|
||||
software not ported to 64bit and architectures in use that are 32bit. Whatever
|
||||
the motivation, the *compilation* process might not be as straight-forward on
|
||||
Arch as one would maybe expect, so this post shows how it can be done. Unless
|
||||
specified otherwise, the `x86` architecture is assumed.
|
||||
|
||||
### Example program
|
||||
|
||||
> Just show the example program already!
|
||||
|
||||
Nothing fancy, just saying hi and printing the value of `esp`. All that is
|
||||
needed is to compile this into a 32bit binary.
|
||||
|
||||
```c
|
||||
/* 32ftw.c */
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("hey 32!\n");
|
||||
|
||||
register int e asm("esp");
|
||||
printf("esp: 0x%08x\n", e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
For reference, the`GCC` version used was `gcc (GCC) 13.1.1 20230429`.
|
||||
|
||||
## TL;DR
|
||||
|
||||
To compile a 32bit `C` program on
|
||||
[64bit-only](https://wiki.archlinux.org/title/Frequently_asked_questions#What_architectures_does_Arch_support?)
|
||||
Arch, additional packages (on top of compilers/linkers) are required. As of
|
||||
2023-06-14 these are:
|
||||
* `core/lib32-glibc`
|
||||
* `core/libr32-gcc-libs`,
|
||||
|
||||
which are the GNU C library (could also use [musl libc](https://musl.libc.org/)
|
||||
but that would probably necessitate compiler wrapping as GCC seems to prefer
|
||||
the GNU versions), and the 32bit version of the GCC libraries, respectively.
|
||||
|
||||
|
||||
### Installing deps and calling it a day
|
||||
|
||||
```sh
|
||||
~ % sudo pacman -S lib32-glibc lib32-gcc-libs
|
||||
resolving dependencies...
|
||||
looking for conflicting packages...
|
||||
|
||||
Package (2) New Version Net Change
|
||||
|
||||
core/lib32-gcc-libs 13.1.1-1 113.12 MiB
|
||||
core/lib32-glibc 2.37-3 18.06 MiB
|
||||
|
||||
Total Installed Size: 131.18 MiB
|
||||
|
||||
:: Proceed with installation? [Y/n]
|
||||
```
|
||||
|
||||
## The longer version
|
||||
|
||||
If you ever needed to compile some `C` sources (such as the example listed
|
||||
[here](#example-program)) on Arch into a 32 bit binary? You might have
|
||||
encountered the following:
|
||||
|
||||
```sh
|
||||
~ % gcc -o 32ftw -m32 32ftw.c && ./32ftw
|
||||
In file included from /usr/include/features.h:515,
|
||||
from /usr/include/bits/libc-header-start.h:33,
|
||||
from /usr/include/stdio.h:27,
|
||||
from 32ftw.c:2:
|
||||
/usr/include/gnu/stubs.h:7:11: fatal error: gnu/stubs-32.h: No such file or directory
|
||||
7 | # include <gnu/stubs-32.h>
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
compilation terminated.
|
||||
```
|
||||
|
||||
Alright, a quick search and [an answer on Arch
|
||||
forums](https://bbs.archlinux.org/viewtopic.php?pid=1136063#p1136063) points to
|
||||
a (spoiler: *partial*) solution: `lib32-glibc` is needed, so let's install it
|
||||
|
||||
```sh
|
||||
~ % sudo pacman -S lib32-glibc
|
||||
```
|
||||
|
||||
and try again:
|
||||
|
||||
```sh
|
||||
~ % gcc -o 32ftw -m32 32ftw.c && ./32ftw
|
||||
/usr/sbin/ld: skipping incompatible /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../libgcc_s.so.1 when searching for libgcc_s.so.1
|
||||
/usr/sbin/ld: skipping incompatible /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../libgcc_s.so.1 when searching for libgcc_s.so.1
|
||||
/usr/sbin/ld: skipping incompatible /usr/lib/libgcc_s.so.1 when searching for libgcc_s.so.1
|
||||
/usr/sbin/ld: cannot find libgcc_s.so.1: No such file or directory
|
||||
/usr/sbin/ld: skipping incompatible /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../libgcc_s.so.1 when searching for libgcc_s.so.1
|
||||
/usr/sbin/ld: skipping incompatible /usr/lib/libgcc_s.so.1 when searching for libgcc_s.so.1
|
||||
collect2: error: ld returned 1 exit status
|
||||
```
|
||||
|
||||
> Oh no, it still refuses to work.
|
||||
|
||||
As is *somewhat* hinted in the linker's error message depicted above, the
|
||||
problem can be rectified by installing the GCC libraries (the 32bit version, of
|
||||
course), which in Arch's `core` repository lives under the name
|
||||
`lib32-gcc-libs`:
|
||||
|
||||
```sh
|
||||
~ % sudo pacman -S lib32-gcc-libs
|
||||
```
|
||||
|
||||
Now the program can finally be compiled and run and we can see it's a 32bit
|
||||
binary.
|
||||
|
||||
```sh
|
||||
~ % gcc -o 32ftw -m32 32ftw.c && ./32ftw
|
||||
hey 32!
|
||||
esp: 0xff8d27f0
|
||||
~ % file ./32ftw
|
||||
32ftw: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=2ff0c8dce8f64db4960aa6aef6cd9936326e990d, for GNU/Linux 4.4.0, not stripped
|
||||
~ % ldd ./32ftw
|
||||
linux-gate.so.1 (0xf7f50000)
|
||||
libc.so.6 => /usr/lib32/libc.so.6 (0xf7ce5000)
|
||||
/lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xf7f52000)
|
||||
```
|
||||
|
||||
## Closing words
|
||||
To sum up, compiling a `C` program for 32bit on contemporary Arch works fine
|
||||
with just a handful of dependencies. In author's opinion, this could be
|
||||
highlighted better in the Archwiki, but perhaps the target audience is so small
|
||||
that it hasn't even been considered.
|
||||
|
||||
For a not-much-talking summary, check out [TL;DR's calling it a
|
||||
day](#installing-deps-and-calling-it-a-day).
|
22
content/privacy.md
Normal file
22
content/privacy.md
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "privacy"
|
||||
description: "an overview of dotya.ml's information collection/use practices (spoiler - we don't sell your data)"
|
||||
date: 2022-08-30T12:47:37+02:00
|
||||
lastmod: 2022-08-30T12:47:37+02:00
|
||||
enableGitInfo: true
|
||||
draft: false
|
||||
---
|
||||
|
||||
### tl;dr
|
||||
[Access logs](https://en.wikipedia.org/wiki/Server_log) are stored for up to 30 days for the purpose of defending against abuse.
|
||||
|
||||
### the long version
|
||||
Since I don't like such practices myself, this site *does not* collect
|
||||
*any* kind of user/browser/device/user agent/network identifier,
|
||||
which - for simplicity's sake is - no data at all - **FOR PROFIT**.\
|
||||
Period.
|
||||
|
||||
No personally identifiable data is collected - actively or passively - and therefore can't be passed on to third parties (such as advertisement companies), nor is there any intention of *ever* doing so.
|
||||
|
||||
Visitor device's apparent IP address *is stored* in access log, along with a [user agent](https://duckduckgo.com/?t=ffab&q=user+agent) string, which allows us to defend against abuse.
|
||||
These logs are automatically overwriten approximately every 30 days.
|
25
content/services.md
Normal file
25
content/services.md
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "services"
|
||||
description: "a non-exhaustive list of services hosted by dotya.ml available to the community"
|
||||
date: 2022-08-30T11:50:50+02:00
|
||||
lastmod: 2022-08-30T11:50:50+02:00
|
||||
enableGitInfo: true
|
||||
toc: true
|
||||
draft: false
|
||||
---
|
||||
|
||||
a non-exhaustive list of services available to the community:
|
||||
* [Gitea](https://gitea.io) SCM instance at https://git.dotya.ml
|
||||
* [DroneCI](https://drone.io) instance (login with a Gitea account) at https://drone.dotya.ml
|
||||
* DNS resolvers:
|
||||
* [DNSCrypt](https://dnscrypt.info/) resolver (see [DNSCrypt]({{< relref "posts/dnscrypt" >}}))
|
||||
* [CoreDNS](https://coredns.io/) serving
|
||||
[DNS-over-TLS](https://www.rfc-editor.org/rfc/rfc7858) at
|
||||
`dns.dotya.ml:853`, and
|
||||
[DNS-over-HTTPS](https://en.wikipedia.org/wiki/DNS_over_HTTPS) at
|
||||
`https://dns.dotya.ml/dns-query`|`https://dns.dotya.ml:4053/dns-query`
|
||||
([config](https://git.dotya.ml/dotya.ml/coredns)).
|
||||
* [SearXNG](https://github.com/searxng/searxng) *metasearch* engine instance at https://searxng.dotya.ml/
|
||||
* [tmate](https://tmate.io/) server (see https://git.dotya.ml/dotya.ml/tmate)
|
||||
|
||||
also check out [onions 🧅]({{< relref "onions" >}}) to learn about services accessible via TOR.
|
@ -1,40 +1,43 @@
|
||||
---
|
||||
|
||||
version: '3'
|
||||
services:
|
||||
reverse-proxy:
|
||||
image: traefik:2.6.2
|
||||
command: --api=false --api.dashboard=false --providers.docker
|
||||
networks:
|
||||
- internal-nw
|
||||
- default
|
||||
ports:
|
||||
- 127.0.0.1:1314:80
|
||||
restart: always
|
||||
volumes:
|
||||
# So that traefik can listen to the Docker events
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
#reverse-proxy:
|
||||
# image: docker.io/library/traefik:2.9.6
|
||||
# command: --api=false --api.dashboard=false --providers.docker
|
||||
# mem_limit: 64m
|
||||
# networks:
|
||||
# - internal-nw
|
||||
# - default
|
||||
# ports:
|
||||
# - 127.0.0.1:1314:80
|
||||
# restart: always
|
||||
# volumes:
|
||||
# # So that traefik can listen to the Docker events
|
||||
# - /run/docker.sock:/var/run/docker.sock:ro
|
||||
# healthcheck:
|
||||
# # DON'T
|
||||
# # test: "/usr/bin/wget -q -Y off http://localhost:80/about -O /dev/null > /dev/null 2>&1"
|
||||
# # DO:
|
||||
# test: "/usr/bin/wget -q -Y off http://localhost:80/about -O /dev/null 2>&-"
|
||||
# interval: 10s
|
||||
# retries: 20
|
||||
|
||||
homepage:
|
||||
build:
|
||||
context: .
|
||||
image: homepage
|
||||
mem_limit: 8m
|
||||
networks:
|
||||
- internal-nw
|
||||
# - internal-nw
|
||||
- default
|
||||
ports:
|
||||
- 127.0.0.1:1314:1314
|
||||
restart: always
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.services.homepage.loadbalancer.server.port=80
|
||||
- traefik.http.routers.homepage.rule=Host(`localhost`) || Host(`127.0.0.1`) || Host(`homepage`) || Host(`6426tqrh4y5uobmo5y2csaip3m3avmjegd2kpa24sadekpxglbm34aqd.onion`)
|
||||
# ref: https://stackoverflow.com/a/61976953
|
||||
# ref: https://github.com/traefik/traefik/issues/563
|
||||
- "traefik.http.routers.homepage.middlewares=homepage-redirectregex, homepage-replacepathregex"
|
||||
|
||||
- "traefik.http.middlewares.homepage-replacepathregex.replacepathregex.regex=^/tags/(.*)$$"
|
||||
- "traefik.http.middlewares.homepage-replacepathregex.replacepathregex.replacement=https://dotya.ml/tags/$$1/"
|
||||
- "traefik.http.middlewares.homepage-redirectregex.redirectregex.regex=^/tags$$"
|
||||
- "traefik.http.middlewares.homepage-redirectregex.redirectregex.replacement=https://dotya.ml/tags/"
|
||||
- "traefik.frontend.redirect.regex=^https://dotya.ml/tags/(.*)$$"
|
||||
- "traefik.frontend.redirect.replacement=https://dotya.ml/tags/$$1/"
|
||||
- "traefik.frontend.rule=PathPrefix:/tags;ReplacePathRegex: ^/tags/(.*) /tags/$$1/"
|
||||
#labels:
|
||||
# - traefik.enable=true
|
||||
# - traefik.http.services.homepage.loadbalancer.server.port=1314
|
||||
# - traefik.http.routers.homepage.rule=Host(`localhost`) || Host(`127.0.0.1`) || Host(`homepage`) || Host(`6426tqrh4y5uobmo5y2csaip3m3avmjegd2kpa24sadekpxglbm34aqd.onion`)
|
||||
|
||||
logging:
|
||||
driver: json-file
|
||||
@ -43,6 +46,11 @@ services:
|
||||
max-file: "5"
|
||||
|
||||
networks:
|
||||
internal-nw:
|
||||
internal: true
|
||||
# internal-nw:
|
||||
# internal: true
|
||||
default:
|
||||
|
||||
volumes:
|
||||
none:
|
||||
|
||||
...
|
||||
|
3
go.mod
Normal file
3
go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module git.dotya.ml/dotya.ml/homepage
|
||||
|
||||
go 1.20
|
@ -1,5 +1,5 @@
|
||||
{{ define "head" }}
|
||||
{{ range .AlternativeOutputFormats -}}
|
||||
{{ with .OutputFormats.Get "rss" -}}
|
||||
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
|
||||
{{ end -}}
|
||||
{{ if .Site.Params.bgImg -}}
|
||||
@ -30,10 +30,10 @@
|
||||
{{ partialCached "menu.html" . }}
|
||||
</nav>
|
||||
</div>
|
||||
<div id="home-footer">
|
||||
<div id="home-footer" role="contentinfo">
|
||||
<p>
|
||||
© {{ now.Format "2006" }} <a href="{{ .Site.BaseURL }}">{{ .Site.Author.name }}</a>{{ .Site.Params.footerCopyright | safeHTML }} · <a href="https://git.dotya.ml/dotya.ml/homepage" title="source code" target="_blank" rel="noopener">source</a> · <a href="https://status.dotya.ml" title="service status" target="_blank" rel="noopener">status</a>
|
||||
{{- with (not (in (.Site.Language.Get "disableKinds") "RSS")) }} · <a href="{{ "index.xml" | absLangURL }}" target="_blank" title="rss"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rss"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg></a>{{ end }}
|
||||
{{- with (not (in (.Site.Params.Language.Get "disabledKinds") "RSS")) }} · <a href="{{ "index.xml" | absLangURL }}" target="_blank" title="rss"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rss"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg></a>{{ end }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,3 +1,3 @@
|
||||
<footer id="site-footer" class="section-inner thin animated fadeIn faster">
|
||||
<footer id="site-footer" class="section-inner thin animated fadeIn faster" role="contentinfo">
|
||||
<p>© {{ now.Format "2006" }} <a href="{{ .Site.BaseURL }}">{{ .Site.Author.name }}</a>{{ .Site.Params.footerCopyright | safeHTML }} · <a href="https://git.dotya.ml/dotya.ml/homepage" title="source code" target="_blank" rel="noopener">source</a> · <a href="https://status.dotya.ml" title="service status" target="_blank" rel="noopener">status</a>{{if .Site.Params.enableGitInfo}}<br/><a href="https://git.dotya.ml/dotya.ml/homepage/commit/{{ .GitInfo.Hash }}" target="_blank" rel="noopener">commit {{ .GitInfo.AbbreviatedHash }}</a>{{end}}</p>
|
||||
</footer>
|
||||
|
File diff suppressed because one or more lines are too long
77
layouts/posts/single.html
Normal file
77
layouts/posts/single.html
Normal file
@ -0,0 +1,77 @@
|
||||
{{ define "head" }}
|
||||
{{ if .Params.featuredImg -}}
|
||||
<style>.bg-img {background-image: url('{{.Params.featuredImg}}');}</style>
|
||||
{{- else if .Params.images -}}
|
||||
{{- range first 1 .Params.images -}}
|
||||
<style>.bg-img {background-image: url('{{. | absURL}}');}</style>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{ end }}
|
||||
|
||||
{{ define "header" }}
|
||||
{{ partial "header.html" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
{{- if (or .Params.images .Params.featuredImg) }}
|
||||
<div class="bg-img"></div>
|
||||
{{- end }}
|
||||
<main class="site-main section-inner animated fadeIn faster">
|
||||
<article class="thin">
|
||||
<header class="post-header">
|
||||
<div class="post-meta"><span>{{ .Date.Format .Site.Params.dateform }}</span></div>
|
||||
<h1>{{ .Title }}</h1>
|
||||
</header>
|
||||
<div class="content">
|
||||
{{ .Content | replaceRE "(<h[1-6] id=\"([^\"]+)\".+)(</h[1-6]+>)" `${1}<a href="#${2}" class="anchor" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path><line x1="8" y1="12" x2="16" y2="12"></line></svg></a>${3}` | safeHTML }}
|
||||
</div>
|
||||
{{- if .Site.Params.relatedPosts }}
|
||||
{{- partial "related-posts.html" . -}}
|
||||
{{- end }}
|
||||
<hr class="post-end">
|
||||
<footer class="post-info">
|
||||
{{- with $.Param "author" }}
|
||||
<p><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-feather"><path d="M20.24 12.24a6 6 0 0 0-8.49-8.49L5 10.5V19h8.5z"></path><line x1="16" y1="8" x2="2" y2="22"></line><line x1="17.5" y1="15" x2="9" y2="15"></line></svg>{{ . }}</p>
|
||||
{{- end }}
|
||||
{{- with .Params.tags }}
|
||||
<p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-tag meta-icon"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7" y2="7"></line></svg>
|
||||
{{- range . -}}
|
||||
<span class="tag"><a href="{{ "tags/" | absLangURL }}{{ . | urlize }}">{{.}}</a></span>
|
||||
{{- end }}
|
||||
</p>
|
||||
{{- end }}
|
||||
<p><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>{{ i18n "wordCount" . }}</p>
|
||||
<p><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-calendar"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>{{ dateFormat .Site.Params.dateformNumTime .Date.Local }}{{- if .Lastmod }} (last modified {{ dateFormat .Site.Params.dateformNumTime .Lastmod }}){{- end -}}</p>
|
||||
{{- if and .GitInfo .Site.Params.gitUrl }}
|
||||
<p><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-git-commit"><circle cx="12" cy="12" r="4"></circle><line x1="1.05" y1="12" x2="7" y2="12"></line><line x1="17.01" y1="12" x2="22.96" y2="12"></line></svg><a href="{{ .Site.Params.gitUrl -}}{{ .GitInfo.Hash }}" target="_blank" rel="noopener">{{ .GitInfo.AbbreviatedHash }}</a> @ {{ dateFormat .Site.Params.dateformNum .GitInfo.AuthorDate.Local }}</p>
|
||||
{{- end }}
|
||||
</footer>
|
||||
</article>
|
||||
{{- if .Params.toc }}
|
||||
<aside id="toc">
|
||||
<div class="toc-title">{{ i18n "tableOfContents" }}</div>
|
||||
{{ .TableOfContents }}
|
||||
</aside>
|
||||
{{- end }}
|
||||
<div class="post-nav thin">
|
||||
{{- with .NextInSection }}
|
||||
<a class="next-post" href="{{ .Permalink }}">
|
||||
<span class="post-nav-label"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg> {{ i18n "newer" }}</span><br><span>{{ .Title }}</span>
|
||||
</a>
|
||||
{{- end }}
|
||||
{{- with .PrevInSection }}
|
||||
<a class="prev-post" href="{{ .Permalink }}">
|
||||
<span class="post-nav-label">{{ i18n "older" }} <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg></span><br><span>{{ .Title }}</span>
|
||||
</a>
|
||||
{{- end }}
|
||||
</div>
|
||||
<div id="comments" class="thin">
|
||||
{{- partial "comments.html" . -}}
|
||||
</div>
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "footer" }}
|
||||
{{ partialCached "footer.html" . }}
|
||||
{{ end }}
|
92
main.go
Normal file
92
main.go
Normal file
@ -0,0 +1,92 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
var version = "development"
|
||||
|
||||
//go:embed public/*
|
||||
var embeddedPublic embed.FS
|
||||
|
||||
// bytes of the 404.html page.
|
||||
var b404 []byte
|
||||
|
||||
// usrIP is a good way to read the src IP this way because we trust our proxy.
|
||||
// largely from: https://stackoverflow.com/a/55738279
|
||||
func usrIP(r *http.Request) string {
|
||||
ip := r.Header.Get("x-forwarded-for")
|
||||
if ip == "" {
|
||||
ip = r.Header.Get("x-real-ip")
|
||||
}
|
||||
|
||||
if ip == "" {
|
||||
ip = r.RemoteAddr
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
// notFound writes back 404 and the 404 page.
|
||||
func notFound(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write(b404)
|
||||
}
|
||||
|
||||
// handleNotFound allows us to override the response on e.g. 404.
|
||||
// inspired by https://stackoverflow.com/a/62747667
|
||||
func handleNotFound(fs http.FileSystem) http.Handler {
|
||||
fileServer := http.FileServer(fs)
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
p := r.URL.Path
|
||||
// so as not to allow path traversals.
|
||||
cleanedPath := path.Clean(p)
|
||||
_, err := fs.Open(cleanedPath)
|
||||
if os.IsNotExist(err) {
|
||||
log.Printf("Error 404 Not Found when serving path: %s, cleaned path: %s, IP: %s",
|
||||
p, cleanedPath, usrIP(r))
|
||||
notFound(w, r)
|
||||
return
|
||||
}
|
||||
fileServer.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
// TODO: ENV WHATPORT
|
||||
// TODO: add /ip endpoint that returns the src IP.
|
||||
f404, err := embeddedPublic.ReadFile("public/404.html")
|
||||
if err != nil {
|
||||
log.Fatalf("no 404.html in the folder, weird: %s", fmt.Errorf("err: %w", err))
|
||||
}
|
||||
|
||||
b404 = f404
|
||||
|
||||
root, err := fs.Sub(embeddedPublic, "public")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Printf("Starting app built from revision '%s'\n", version)
|
||||
log.Print("Listening on :1314...")
|
||||
|
||||
// https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/
|
||||
srv := http.Server{
|
||||
ReadTimeout: 15 * time.Second,
|
||||
WriteTimeout: 15 * time.Second,
|
||||
Addr: ":1314",
|
||||
Handler: handleNotFound(http.FS(root)),
|
||||
}
|
||||
|
||||
err = srv.ListenAndServe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user