diff --git a/.travis.yml b/.travis.yml index fd369c2e..b2e5a2dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -86,7 +86,7 @@ matrix: - node -v - npm -v # Prepare releases - - ./release.sh + - ./build_release.sh - ls -l dist deploy: @@ -118,4 +118,4 @@ matrix: - docker login -u="$DOCKER_USER" -p="$DOCKER_PASSWORD" - ./build_docker.sh after_script: - - docker images + - docker images diff --git a/Makefile b/Makefile index 74934562..ff32c957 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ GOPATH := $(shell go env GOPATH) JSFILES = $(shell find client -path client/node_modules -prune -o -type f -name '*.js') STATIC = build/static/index.html CHANNEL ?= release +DOCKER_IMAGE_DEV_NAME=adguardhome-dev +DOCKERFILE=packaging/docker/Dockerfile +DOCKERFILE_HUB=packaging/docker/Dockerfile.travis TARGET=AdGuardHome @@ -26,6 +29,11 @@ $(TARGET): $(STATIC) *.go home/*.go dhcpd/*.go dnsfilter/*.go dnsforward/*.go CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=$(GIT_VERSION) -X main.channel=$(CHANNEL) -X main.goarm=$(GOARM)" -asmflags="-trimpath=$(PWD)" -gcflags="-trimpath=$(PWD)" PATH=$(GOPATH)/bin:$(PATH) packr clean +docker: + docker build -t "$(DOCKER_IMAGE_DEV_NAME)" -f "$(DOCKERFILE)" . + @echo Now you can run the docker image: + @echo docker run --name "$(DOCKER_IMAGE_DEV_NAME)" -p 53:53/tcp -p 53:53/udp -p 3000:3000/tcp $(DOCKER_IMAGE_DEV_NAME) + clean: $(MAKE) cleanfast rm -rf build diff --git a/build_docker.sh b/build_docker.sh index 1123d269..81173574 100755 --- a/build_docker.sh +++ b/build_docker.sh @@ -4,7 +4,7 @@ set -eE set -o pipefail set -x -DOCKERFILE="Dockerfile.travis" +DOCKERFILE="packaging/docker/Dockerfile.hub" IMAGE_NAME="adguard/adguardhome" if [[ "${TRAVIS_BRANCH}" == "master" ]] diff --git a/release.sh b/build_release.sh similarity index 100% rename from release.sh rename to build_release.sh diff --git a/build_snap.sh b/build_snap.sh new file mode 100755 index 00000000..8879fd22 --- /dev/null +++ b/build_snap.sh @@ -0,0 +1,270 @@ +#!/usr/bin/env bash + +set -eE +set -o pipefail +set -x + +BUILDER_IMAGE="adguard/snapcraft:1.0" +SNAPCRAFT_TMPL="packaging/snap/snapcraft.yaml" +SNAP_NAME="adguardhometest" +LAUNCHPAD_CREDENTIALS_DIR=".local/share/snapcraft/provider/launchpad" + +if [[ -z ${VERSION} ]]; then + VERSION=`git describe --abbrev=4 --dirty --always --tags` + echo "VERSION env variable is not set, getting it from git: ${VERSION}" +fi + +# If bash is interactive, set `-it` parameter for docker run +INTERACTIVE="" +if [ -t 0 ] ; then + INTERACTIVE="-it" +fi + +function usage() { + cat < launchpad_credentials + + # Snapcraft login data + # It can be exported using snapcraft export-login command + echo "[login.ubuntu.com] + macaroon = ${SNAPCRAFT_MACAROON} + unbound_discharge = ${SNAPCRAFT_UBUNTU_DISCHARGE} + email = ${SNAPCRAFT_EMAIL}" > snapcraft_login + + # Prepare the snap configuration + cp ${SNAPCRAFT_TMPL} ./snapcraft.yaml + sed -i.bak 's/dev_version/'"${VERSION}"'/g' ./snapcraft.yaml + rm -f snapcraft.yaml.bak +} + +build_snap() { + # prepare credentials + prepare + + # copy them to the directory where snapcraft will be able to read them + mkdir -p ~/${LAUNCHPAD_CREDENTIALS_DIR} + cp -f snapcraft_login ~/${LAUNCHPAD_CREDENTIALS_DIR}/credentials + chmod 600 ~/${LAUNCHPAD_CREDENTIALS_DIR}/credentials + + # run the build + snapcraft remote-build --build-on=${ARCH} --launchpad-accept-public-upload + + # remove the credentials - we don't need them anymore + rm -rf ~/${LAUNCHPAD_CREDENTIALS_DIR} + + # remove version from the file name + rename_snap_file + + # cleanup credentials + cleanup +} + +build_snap_docker() { + # prepare credentials + prepare + + docker run ${INTERACTIVE} --rm \ + -v $(pwd):/build \ + -v $(pwd)/launchpad_credentials:/root/${LAUNCHPAD_CREDENTIALS_DIR}/credentials:ro \ + ${BUILDER_IMAGE} \ + snapcraft remote-build --build-on=${ARCH} --launchpad-accept-public-upload + + # remove version from the file name + rename_snap_file + + # cleanup credentials + cleanup +} + +rename_snap_file() { + # In order to make working with snaps easier later on + # we remove version from the file name + + # Check that the snap file exists + snapFile="${SNAP_NAME}_${VERSION}_${ARCH}.snap" + if [ ! -f ${snapFile} ]; then + echo "Snap file ${snapFile} not found!" + exit 1 + fi + + mv -f ${snapFile} "${SNAP_NAME}_${ARCH}.snap" +} + +publish_snap() { + # prepare credentials + prepare + + # Check that the snap file exists + snapFile="${SNAP_NAME}_${ARCH}.snap" + if [ ! -f ${snapFile} ]; then + echo "Snap file ${snapFile} not found!" + exit 1 + fi + + # Login if necessary + snapcraft login --with=snapcraft_login + + # Push to the channel + snapcraft push --release=${CHANNEL} ${snapFile} + + # cleanup credentials + cleanup +} + +publish_snap_docker() { + # prepare credentials + prepare + + # Check that the snap file exists + snapFile="${SNAP_NAME}_${ARCH}.snap" + if [ ! -f ${snapFile} ]; then + echo "Snap file ${snapFile} not found!" + exit 1 + fi + + # Login and publish the snap + docker run ${INTERACTIVE} --rm \ + -v $(pwd):/build \ + ${BUILDER_IMAGE} \ + sh -c "snapcraft login --with=/build/snapcraft_login && snapcraft push --release=${CHANNEL} /build/${snapFile}" + + # cleanup credentials + cleanup +} + +####################################### +# main functions +####################################### + +build() { + ARCH=i386 build_snap + ARCH=arm64 build_snap + ARCH=armhf build_snap + ARCH=amd64 build_snap +} + +build_docker() { + ARCH=i386 build_snap_docker + ARCH=arm64 build_snap_docker + ARCH=armhf build_snap_docker + ARCH=amd64 build_snap_docker +} + +publish_docker() { + if [[ -z $1 ]]; then + echo "No channel specified" + exit 1 + fi + CHANNEL="${1}" + if [ "$CHANNEL" != "release" ] && [ "$CHANNEL" != "beta" ]; then + echo "$CHANNEL is an invalid value for the update channel!" + exit 1 + fi + + ARCH=i386 publish_snap_docker + ARCH=arm64 publish_snap_docker + ARCH=armhf publish_snap_docker + ARCH=amd64 publish_snap_docker +} + +publish() { + if [[ -z $1 ]]; then + echo "No channel specified" + exit 1 + fi + CHANNEL="${1}" + if [ "$CHANNEL" != "release" ] && [ "$CHANNEL" != "beta" ]; then + echo "$CHANNEL is an invalid value for the update channel!" + exit 1 + fi + + ARCH=i386 publish_snap + ARCH=arm64 publish_snap + ARCH=armhf publish_snap + ARCH=amd64 publish_snap +} + +cleanup() { + rm -f launchpad_credentials + rm -f snapcraft.yaml + rm -f snapcraft.yaml.bak + rm -f snapcraft_login +} + +####################################### +# main +####################################### +if [[ -z $1 || $1 == "--help" || $1 == "-h" ]]; then + usage +fi + +case "$1" in +"build-docker") build_docker ;; +"build") build ;; +"publish-docker-beta") publish_docker beta ;; +"publish-docker-release") publish_docker release ;; +"publish-beta") publish beta ;; +"publish-release") publish release ;; +"cleanup") cleanup ;; +*) usage ;; +esac + +exit 0 \ No newline at end of file diff --git a/Dockerfile b/packaging/docker/Dockerfile similarity index 100% rename from Dockerfile rename to packaging/docker/Dockerfile diff --git a/packaging/docker/Dockerfile.hub b/packaging/docker/Dockerfile.hub new file mode 100644 index 00000000..0e11574e --- /dev/null +++ b/packaging/docker/Dockerfile.hub @@ -0,0 +1,23 @@ +FROM alpine:latest +LABEL maintainer="AdGuard Team " + +# Update CA certs +RUN apk --no-cache --update add ca-certificates libcap && \ + rm -rf /var/cache/apk/* && \ + mkdir -p /opt/adguardhome/conf /opt/adguardhome/work && \ + chown -R nobody: /opt/adguardhome + +COPY --chown=nobody:nogroup ./AdGuardHome /opt/adguardhome/AdGuardHome + +RUN setcap 'cap_net_bind_service=+eip' /opt/adguardhome/AdGuardHome + +EXPOSE 53/tcp 53/udp 67/udp 68/udp 80/tcp 443/tcp 853/tcp 3000/tcp + +VOLUME ["/opt/adguardhome/conf", "/opt/adguardhome/work"] + +WORKDIR /opt/adguardhome/work + +#USER nobody + +ENTRYPOINT ["/opt/adguardhome/AdGuardHome"] +CMD ["-h", "0.0.0.0", "-c", "/opt/adguardhome/conf/AdGuardHome.yaml", "-w", "/opt/adguardhome/work", "--no-check-update"] diff --git a/packaging/docker/README.md b/packaging/docker/README.md new file mode 100644 index 00000000..0d7ff06f --- /dev/null +++ b/packaging/docker/README.md @@ -0,0 +1,6 @@ +## Docker images + +* `Dockerfile` is used for local development. Build it using `make docker` command. + +* `Dockerfile.hub` is used to publish AdGuard images to Docker Hub: https://hub.docker.com/r/adguard/adguardhome + Check out `build_docker.sh` for the details. \ No newline at end of file diff --git a/packaging/snap/README.md b/packaging/snap/README.md new file mode 100644 index 00000000..764100ff --- /dev/null +++ b/packaging/snap/README.md @@ -0,0 +1,5 @@ +## Snapcraft + +Configuration for our snap. + +Check out `build_snap.sh` for more details. \ No newline at end of file diff --git a/packaging/snap/snapcraft.yaml b/packaging/snap/snapcraft.yaml new file mode 100644 index 00000000..ba7a47d0 --- /dev/null +++ b/packaging/snap/snapcraft.yaml @@ -0,0 +1,31 @@ +name: adguardhometest +base: core18 +version: 'dev_version' +summary: Network-wide ads & trackers blocking DNS server +description: | + AdGuard Home is a network-wide software for blocking ads & tracking. After + you set it up, it'll cover ALL your home devices, and you don't need any + client-side software for that. + It operates as a DNS server that re-routes tracking domains to a "black hole," + thus preventing your devices from connecting to those servers. It's based + on software we use for our public AdGuard DNS servers -- both share a lot + of common code. +grade: stable +confinement: strict + +parts: + adguard-home: + plugin: make + source: . + build-snaps: [ node/13/stable, go ] + build-packages: [ git, build-essential ] + override-build: | + make clean + make + cp AdGuardHome ${SNAPCRAFT_PART_INSTALL}/ +apps: + adguard-home: + command: AdGuardHome -c ${SNAP_COMMON}/AdGuardHome.yaml -w ${SNAP_DATA} --no-check-update + plugs: [ network-bind ] + daemon: simple + restart-condition: always \ No newline at end of file