diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 900a3e57eec4ff9c5622228c20990aa266fbf5dc..9fbd5a8ffc476c48f23f252e7bafc7ed23ee468e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,12 +13,15 @@ include:
 
 variables:
   FDO_UPSTREAM_REPO: xrdesktop/libinputsynth
-
+  # increment to easily rebuild all images
+  GLOBAL_TAG_SUFFIX: 2
 
 stages:
   - container_prep
   - build_and_test
-
+  - package
+  - reprepro
+  - pages
 
 # "Base" job for a Meson build
 .xrdesktop.base-job.build-meson:
@@ -31,37 +34,41 @@ stages:
 # variables shared by container_prep and build jobs
 .xrdesktop.variables.arch:rolling:
   variables:
-    FDO_DISTRIBUTION_TAG: "2021-03-21.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
 
 .xrdesktop.variables.ubuntu:focal:
   variables:
     FDO_DISTRIBUTION_VERSION: "20.04"
-    FDO_DISTRIBUTION_TAG: "2021-03-21.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
 
 .xrdesktop.variables.ubuntu:groovy:
   variables:
     FDO_DISTRIBUTION_VERSION: "20.10"
-    FDO_DISTRIBUTION_TAG: "2021-03-21.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
 
 .xrdesktop.variables.ubuntu:hirsute:
   variables:
     FDO_DISTRIBUTION_VERSION: "21.04"
-    FDO_DISTRIBUTION_TAG: "2021-05-19.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
 
 .xrdesktop.variables.debian:buster:
   variables:
     FDO_DISTRIBUTION_VERSION: "buster"
-    FDO_DISTRIBUTION_TAG: "2021-05-19.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
 
 .xrdesktop.variables.debian:bullseye:
   variables:
     FDO_DISTRIBUTION_VERSION: "bullseye"
-    FDO_DISTRIBUTION_TAG: "2021-05-19.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
 
 .xrdesktop.variables.debian:sid:
   variables:
     FDO_DISTRIBUTION_VERSION: "sid"
-    FDO_DISTRIBUTION_TAG: "2021-05-19.0"
+    FDO_DISTRIBUTION_TAG: "2021-07-26.${GLOBAL_TAG_SUFFIX}.0"
+
+.xrdesktop.variables.debian-based-packages:
+  variables:
+    CORE_REQUIRED_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev git apt-utils reprepro build-essential devscripts debhelper dput-ng gettext-base gtk-doc-tools"
 
 
 # === Archlinux ===
@@ -102,8 +109,9 @@ ubuntu:focal:container_prep:
   extends:
     - .xrdesktop.variables.ubuntu:focal
     - .fdo.container-build@ubuntu # from ci-templates
+    - .xrdesktop.variables.debian-based-packages
   variables:
-    FDO_DISTRIBUTION_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev"
+    FDO_DISTRIBUTION_PACKAGES: "${CORE_REQUIRED_PACKAGES}"
 
 ubuntu:focal:gcc:
   extends:
@@ -123,8 +131,9 @@ ubuntu:groovy:container_prep:
   extends:
     - .xrdesktop.variables.ubuntu:groovy
     - .fdo.container-build@ubuntu # from ci-templates
+    - .xrdesktop.variables.debian-based-packages
   variables:
-    FDO_DISTRIBUTION_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev"
+    FDO_DISTRIBUTION_PACKAGES: "${CORE_REQUIRED_PACKAGES}"
 
 ubuntu:groovy:gcc:
   extends:
@@ -143,8 +152,9 @@ ubuntu:hirsute:container_prep:
   extends:
     - .xrdesktop.variables.ubuntu:hirsute
     - .fdo.container-build@ubuntu # from ci-templates
+    - .xrdesktop.variables.debian-based-packages
   variables:
-    FDO_DISTRIBUTION_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev"
+    FDO_DISTRIBUTION_PACKAGES: "${CORE_REQUIRED_PACKAGES}"
 
 ubuntu:hirsute:gcc:
   extends:
@@ -164,8 +174,9 @@ debian:buster:container_prep:
   extends:
     - .xrdesktop.variables.debian:buster
     - .fdo.container-build@debian # from ci-templates
+    - .xrdesktop.variables.debian-based-packages
   variables:
-    FDO_DISTRIBUTION_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev"
+    FDO_DISTRIBUTION_PACKAGES: "${CORE_REQUIRED_PACKAGES}"
 
 debian:buster:gcc:
   extends:
@@ -185,8 +196,9 @@ debian:bullseye:container_prep:
   extends:
     - .xrdesktop.variables.debian:bullseye
     - .fdo.container-build@debian # from ci-templates
+    - .xrdesktop.variables.debian-based-packages
   variables:
-    FDO_DISTRIBUTION_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev"
+    FDO_DISTRIBUTION_PACKAGES: "${CORE_REQUIRED_PACKAGES}"
 
 debian:bullseye:gcc:
   extends:
@@ -206,8 +218,9 @@ debian:sid:container_prep:
   extends:
     - .xrdesktop.variables.debian:sid
     - .fdo.container-build@debian # from ci-templates
+    - .xrdesktop.variables.debian-based-packages
   variables:
-    FDO_DISTRIBUTION_PACKAGES: "meson gcc pkg-config libglib2.0-dev libxdo-dev"
+    FDO_DISTRIBUTION_PACKAGES: "${CORE_REQUIRED_PACKAGES}"
 
 debian:sid:gcc:
   extends:
@@ -218,3 +231,182 @@ debian:sid:gcc:
     MESON_ARGS: -Ddocs=disabled
     CC: gcc
     CXX: g++
+
+
+# Packaging
+.xrdesktop.packaging.conditions:
+  rules:
+    # Only the default branch of the "upstream" repo.
+    - if: '$CI_PROJECT_PATH == $FDO_UPSTREAM_REPO && $CI_COMMIT_REF_NAME == "master"'
+      when: on_success
+    # Otherwise, don't build packages.
+    #- when: never
+    - when: on_success
+
+
+# Packaging
+.xrdesktop.base-job.debuild:
+  extends:
+    - .xrdesktop.packaging.conditions
+  stage: package
+  before_script:
+    # Configure git - needed despite not actually committing here.
+    - git config --global user.email "christoph.haag@collabora.com"
+    - git config --global user.name "xrdesktop CI"
+  script:
+    # Prep the source tree
+    - git clean -dfx
+    - git remote -v
+    - git fetch --unshallow
+    - git fetch origin
+    - git fetch origin --tags
+    - rm -rf debian
+    - cp -ra ${PACKAGE_DIR} debian
+    - DEBFULLNAME="xrdesktop CI <christoph.haag@collabora.com>" DEBEMAIL="christoph.haag@collabora.com" debian/extra/prepare-commit-package.sh ${CI_COMMIT_SHA} 1~${BACKPORT_SUFFIX}~ci$(date --utc "+%Y%m%d")
+    # Build the package
+    - debuild -uc -us -d -sa
+    # Use dput-ng to move the package-related files into some artifacts.
+    - export INCOMING=$(pwd)/incoming
+    - mkdir -p $INCOMING
+    - mkdir -p ~/.dput.d/profiles
+    - cat .gitlab-ci/localhost.json | envsubst  > ~/.dput.d/profiles/localhost.json
+    - dpkg-parsechangelog --show-field version > incoming/${DISTRO}.distro
+    - dput --force --debug localhost ../libinputsynth_$(dpkg-parsechangelog --show-field version)_amd64.changes
+  artifacts:
+    paths:
+      - "incoming/"
+    expire_in: 2 days
+
+
+debian:buster:package:
+  extends:
+    - .xrdesktop.variables.debian:buster
+    - .fdo.distribution-image@debian # from ci-templates
+    - .xrdesktop.base-job.debuild
+  variables:
+    BACKPORT_SUFFIX: bpo8
+    PACKAGE_DIR:  .gitlab-ci/debian_sid
+    DISTRO: buster
+
+
+debian:bullseye:package:
+  extends:
+    - .xrdesktop.variables.debian:bullseye
+    - .fdo.distribution-image@debian # from ci-templates
+    - .xrdesktop.base-job.debuild
+  variables:
+    BACKPORT_SUFFIX: bpo9
+    PACKAGE_DIR:  .gitlab-ci/debian_sid
+    DISTRO: bullseye
+
+
+debian:sid:package:
+  extends:
+    - .xrdesktop.variables.debian:sid
+    - .fdo.distribution-image@debian # from ci-templates
+    - .xrdesktop.base-job.debuild
+  variables:
+    BACKPORT_SUFFIX: bpo10
+    PACKAGE_DIR:  .gitlab-ci/debian_sid
+    DISTRO: sid
+
+
+ubuntu:focal:package:
+  extends:
+    - .xrdesktop.variables.ubuntu:focal
+    - .fdo.distribution-image@ubuntu # from ci-templates
+    - .xrdesktop.base-job.debuild
+  variables:
+    BACKPORT_SUFFIX: ubuntu20.04
+    PACKAGE_DIR:  .gitlab-ci/debian_sid
+    DISTRO: focal
+
+
+ubuntu:groovy:package:
+  extends:
+    - .xrdesktop.variables.ubuntu:groovy
+    - .fdo.distribution-image@ubuntu # from ci-templates
+    - .xrdesktop.base-job.debuild
+  variables:
+    BACKPORT_SUFFIX: ubuntu20.10
+    PACKAGE_DIR:  .gitlab-ci/debian_sid
+    DISTRO: groovy
+
+
+ubuntu:hirsute:package:
+  extends:
+    - .xrdesktop.variables.ubuntu:hirsute
+    - .fdo.distribution-image@ubuntu # from ci-templates
+    - .xrdesktop.base-job.debuild
+  variables:
+    BACKPORT_SUFFIX: ubuntu21.04
+    PACKAGE_DIR:  .gitlab-ci/debian_sid
+    DISTRO: hirsute
+
+
+reprepro:package:
+  stage: reprepro
+  extends:
+    - .xrdesktop.variables.debian:sid
+    - .xrdesktop.packaging.conditions
+    - .fdo.distribution-image@debian # from ci-templates
+  dependencies:
+    - debian:buster:package
+    - debian:bullseye:package
+    - debian:sid:package
+    - ubuntu:focal:package
+    - ubuntu:groovy:package
+    - ubuntu:hirsute:package
+  before_script:
+    # Convince gnupg to work properly in CI
+    - mkdir -p ~/.gnupg && chmod 700 ~/.gnupg
+    - touch ~/.gnupg/gpg.conf
+    - echo 'use-agent' > ~/.gnupg/gpg.conf
+    - echo 'pinentry-mode loopback' >> ~/.gnupg/gpg.conf
+    - touch ~/.gnupg/gpg-agent.conf
+    - echo 'allow-loopback-pinentry' > ~/.gnupg/gpg-agent.conf
+    - echo RELOADAGENT | gpg-connect-agent
+    - gpg --batch --no-tty --yes --pinentry-mode loopback --passphrase ${XRDESKTOP_GPG_PASSPHRASE} --import ${XRDESKTOP_GPG_SECRET_KEY}
+
+  script:
+    # Use reprepro to create an apt repository in our artifacts
+    - mkdir -p repo/conf
+    # For each distro, sign the changes file and add it to the repo.
+    - |
+      for fn in incoming/*.distro; do
+        # parse the distro name out
+        export DISTRO=$(echo $fn | sed -e 's:incoming/::' -e 's:[.]distro::')
+        echo "Processing $DISTRO"
+        # add distro to repository config - blank line is mandatory!
+        cat .gitlab-ci/distributions | envsubst >> repo/conf/distributions
+        echo >> repo/conf/distributions
+
+        echo "Signing package for $DISTRO"
+        debsign -k ${XRDESKTOP_GPG_FINGERPRINT} -p "gpg --batch --no-tty --yes --pinentry-mode loopback --passphrase ${XRDESKTOP_GPG_PASSPHRASE}" incoming/libinputsynth_$(cat $fn)_amd64.changes
+
+        echo "Adding package for $DISTRO to the repository"
+        reprepro -V --ignore=wrongdistribution -b repo include ${DISTRO} incoming/libinputsynth_$(cat $fn)_amd64.changes
+      done
+  artifacts:
+    paths:
+      - "repo/"
+    expire_in: 2 days
+
+
+###
+# Pages
+###
+pages:
+  stage: pages
+  extends:
+    - .xrdesktop.packaging.conditions
+  dependencies:
+    - reprepro:package
+  script:
+    - mkdir -p public
+    # - mv build/doc/html/* public/
+    - mv repo public/apt
+  artifacts:
+    paths:
+      - public
+
diff --git a/.gitlab-ci/debian_sid/changelog b/.gitlab-ci/debian_sid/changelog
new file mode 100644
index 0000000000000000000000000000000000000000..534bd5c6b3a5fa6474ef5ffec19306aae09ca829
--- /dev/null
+++ b/.gitlab-ci/debian_sid/changelog
@@ -0,0 +1,57 @@
+libinputsynth (0.15.0-2) unstable; urgency=medium
+
+  * Source only upload.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Sat, 18 Jul 2020 08:00:58 +0800
+
+libinputsynth (0.15.0-1) experimental; urgency=medium
+
+  * New upstream release.
+  * Rename shared library package for soname bump.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Thu, 16 Jul 2020 07:08:06 +0800
+
+libinputsynth (0.14.0-2) unstable; urgency=medium
+
+  * Source only upload.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Tue, 14 Apr 2020 17:25:45 +0800
+
+libinputsynth (0.14.0-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Wed, 01 Apr 2020 09:02:34 +0800
+
+libinputsynth (0.13.2-2) unstable; urgency=medium
+
+  [ Helmut Grohne ]
+  * Fix FTCBFS: (Closes: #941238)
+    + Honour DEB_BUILD_OPTIONS=nocheck.
+    + Fix build/host confusion.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Wed, 11 Dec 2019 12:32:32 +0800
+
+libinputsynth (0.13.2-1) unstable; urgency=medium
+
+  * New upstream version 0.13.2 release.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Mon, 25 Nov 2019 13:53:05 +0800
+
+libinputsynth (0.13.1-1) unstable; urgency=medium
+
+  * New upstream version 0.13.1 release.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Wed, 13 Nov 2019 18:26:24 +0800
+
+libinputsynth (0.13.0-1) unstable; urgency=medium
+
+  * New upstream version 0.13.0 release.
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Sat, 12 Oct 2019 18:21:43 +0800
+
+libinputsynth (0.12.1-1) unstable; urgency=medium
+
+  * Initial Release. (Closes: #933563)
+
+ -- Andrew Lee (李健秋) <ajqlee@debian.org>  Sat, 03 Aug 2019 19:11:32 +0800
diff --git a/.gitlab-ci/debian_sid/compat b/.gitlab-ci/debian_sid/compat
new file mode 100644
index 0000000000000000000000000000000000000000..b4de3947675361a7770d29b8982c407b0ec6b2a0
--- /dev/null
+++ b/.gitlab-ci/debian_sid/compat
@@ -0,0 +1 @@
+11
diff --git a/.gitlab-ci/debian_sid/control b/.gitlab-ci/debian_sid/control
new file mode 100644
index 0000000000000000000000000000000000000000..a0bc7b69f11c10a5f272feafa140f0b0d74c2485
--- /dev/null
+++ b/.gitlab-ci/debian_sid/control
@@ -0,0 +1,35 @@
+Source: libinputsynth
+Priority: optional
+Maintainer: Andrew Lee (李健秋) <ajqlee@debian.org>
+Uploaders: Héctor Orón Martínez <zumbi@debian.org>
+Build-Depends: debhelper (>= 11),
+ meson (>= 0.45.1),
+ libglib2.0-dev,
+ libx11-dev,
+ libxtst-dev,
+ libxi-dev,
+ libxdo-dev
+Standards-Version: 4.3.0
+Section: libs
+Homepage: https://gitlab.freedesktop.org/xrdesktop/libinputsynth
+Vcs-Browser: https://salsa.debian.org/xrdesktop-team/libinputsynth
+Vcs-Git: https://salsa.debian.org/xrdesktop-team/libinputsynth.git
+
+Package: libinputsynth-dev
+Section: libdevel
+Architecture: any
+Multi-Arch: same
+Depends: libinputsynth-0.15-0 (= ${binary:Version}), ${misc:Depends}
+Description: synthesize keyboard and mouse input -- development files
+ synthesize keyboard and mouse input on X11 and Wayland with various backends.
+ .
+ This package includes files needed for development.
+
+Package: libinputsynth-0.15-0
+Architecture: any
+Multi-Arch: same
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: synthesize keyboard and mouse input
+ synthesize keyboard and mouse input on X11 and Wayland with various backends.
+ .
+ This package includes the loader library.
diff --git a/.gitlab-ci/debian_sid/copyright b/.gitlab-ci/debian_sid/copyright
new file mode 100644
index 0000000000000000000000000000000000000000..599d627461b41eb7a75933e03614def76c459a4e
--- /dev/null
+++ b/.gitlab-ci/debian_sid/copyright
@@ -0,0 +1,45 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: libinputsynth
+Source: https://gitlab.freedesktop.org/xrdesktop/libinputsynth
+
+Files: *
+Copyright: 2018-2019 Collabora Ltd
+License: Expat
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+Files: debian/*
+Copyright: 2019 Héctor Orón Martínez <zumbi@debian.org>
+           2019 Andrew Lee (李健秋) <ajqlee@debian.org>
+License: GPL-2+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
+
diff --git a/.gitlab-ci/debian_sid/extra/prepare-commit-package.sh b/.gitlab-ci/debian_sid/extra/prepare-commit-package.sh
new file mode 100755
index 0000000000000000000000000000000000000000..131db71f67234fec5c51adf1147289bb7bb4a6ac
--- /dev/null
+++ b/.gitlab-ci/debian_sid/extra/prepare-commit-package.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright 2020, Ryan Pavlik <ryan@ryanpavlik.com>
+# SPDX-License-Identifier: CC0-1.0
+
+# Packages produced this way are for automated use only and shouldn't be uploaded to the Debian archive.
+
+set -e
+(
+    cd "$(dirname $0)"
+    cd ../..
+    export DEVSCRIPTS_CHECK_DIRNAME_LEVEL=0
+
+    if [ x"$1" != x ]; then
+        COMMIT_TO_PACKAGE=$1
+        export COMMIT_TO_PACKAGE
+    else
+        COMMIT_TO_PACKAGE=master
+        export COMMIT_TO_PACKAGE
+    fi
+
+    if [ x"$2" != x ]; then
+        PKG_REVISION=$2
+        export PKG_REVISION
+    else
+        PKG_REVISION=1~ci$(date --utc "+%Y%m%d")
+        export PKG_REVISION
+    fi
+
+    UPSTREAM_VER=$(git describe --abbrev=0 --tags $COMMIT_TO_PACKAGE | sed -E -e 's/^v//' -e 's/-([0-9]+)-g([0-9a-f])/+git\1.\2/')
+    git archive -o "../libinputsynth_${UPSTREAM_VER}.orig.tar.gz" ${COMMIT_TO_PACKAGE}
+    dch -b --newversion "${UPSTREAM_VER}-${PKG_REVISION}" --preserve "Automated CI build of commit ${COMMIT_TO_PACKAGE}"
+)
diff --git a/.gitlab-ci/debian_sid/libinputsynth-0.15-0.install b/.gitlab-ci/debian_sid/libinputsynth-0.15-0.install
new file mode 100644
index 0000000000000000000000000000000000000000..b988efa78c2311982ec8543c16051560bf6965c1
--- /dev/null
+++ b/.gitlab-ci/debian_sid/libinputsynth-0.15-0.install
@@ -0,0 +1,3 @@
+usr/lib/*/lib*.so.*
+usr/lib/*/*/plugins/lib*.so
+
diff --git a/.gitlab-ci/debian_sid/libinputsynth-dev.install b/.gitlab-ci/debian_sid/libinputsynth-dev.install
new file mode 100644
index 0000000000000000000000000000000000000000..7df81cd9f2a1282cd8d7222dd9b841258c579f78
--- /dev/null
+++ b/.gitlab-ci/debian_sid/libinputsynth-dev.install
@@ -0,0 +1,3 @@
+usr/include/*
+usr/lib/*/lib*.so
+usr/lib/*/pkgconfig/*
diff --git a/.gitlab-ci/debian_sid/rules b/.gitlab-ci/debian_sid/rules
new file mode 100755
index 0000000000000000000000000000000000000000..53c27d2967b8ba936894996a8aa9e25a64aef175
--- /dev/null
+++ b/.gitlab-ci/debian_sid/rules
@@ -0,0 +1,20 @@
+#!/usr/bin/make -f
+
+include /usr/share/dpkg/default.mk
+
+%:
+	dh $@
+
+test_env = LIBINPUTSYNTH_PLUGINDIR=$(CURDIR)/obj-$(DEB_BUILD_GNU_TYPE)/src/ \
+	   LC_ALL=C.UTF-8 \
+	   MESON_TESTTHREADS=1 \
+	   LC_ALL=C.UTF-8 \
+	   MESON_TESTTHREADS=1
+
+override_dh_auto_test:
+ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
+	env $(test_env) ninja -C obj-$(DEB_HOST_GNU_TYPE) test
+endif
+
+override_dh_missing:
+	dh_missing --list-missing
diff --git a/.gitlab-ci/debian_sid/source/format b/.gitlab-ci/debian_sid/source/format
new file mode 100644
index 0000000000000000000000000000000000000000..163aaf8d82b6c54f23c45f32895dbdfdcc27b047
--- /dev/null
+++ b/.gitlab-ci/debian_sid/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/.gitlab-ci/distributions b/.gitlab-ci/distributions
new file mode 100644
index 0000000000000000000000000000000000000000..3a563ee02939bc0391aed3ca8f24362fdfdaffa0
--- /dev/null
+++ b/.gitlab-ci/distributions
@@ -0,0 +1,7 @@
+Origin: xrdesktop.freedesktop.org
+Description: xrdesktop CI apt repository
+Codename: ${DISTRO}
+Architectures: amd64 i386 source
+Components: main
+Tracking: minimal
+SignWith: ${XRDESKTOP_GPG_FINGERPRINT}
diff --git a/.gitlab-ci/distributions.license b/.gitlab-ci/distributions.license
new file mode 100644
index 0000000000000000000000000000000000000000..972ecf740ac215242b92e595d96fe2e7413a9bdd
--- /dev/null
+++ b/.gitlab-ci/distributions.license
@@ -0,0 +1,3 @@
+Copyright 2020, Collabora, Ltd.
+
+SPDX-License-Identifier: BSL-1.0
\ No newline at end of file
diff --git a/.gitlab-ci/localhost.json b/.gitlab-ci/localhost.json
new file mode 100644
index 0000000000000000000000000000000000000000..5ec595751fb35b2def7abc709b33e65d571f3e45
--- /dev/null
+++ b/.gitlab-ci/localhost.json
@@ -0,0 +1,14 @@
+{
+    "+hooks": [
+    ],
+    "-hooks": [
+        "gpg",
+        "allowed-distribution",
+        "suite-mismatch",
+        "lintian"
+    ],
+    "incoming": "${INCOMING}",
+    "meta": "debian",
+    "method": "local",
+    "run_lintian": false
+}
diff --git a/.gitlab-ci/localhost.json.license b/.gitlab-ci/localhost.json.license
new file mode 100644
index 0000000000000000000000000000000000000000..972ecf740ac215242b92e595d96fe2e7413a9bdd
--- /dev/null
+++ b/.gitlab-ci/localhost.json.license
@@ -0,0 +1,3 @@
+Copyright 2020, Collabora, Ltd.
+
+SPDX-License-Identifier: BSL-1.0
\ No newline at end of file
diff --git a/.gitlab-ci/xrdesktop_ci_signing_key_0x7C668346_public.asc b/.gitlab-ci/xrdesktop_ci_signing_key_0x7C668346_public.asc
new file mode 100644
index 0000000000000000000000000000000000000000..455f8bbccbc512088a48e1d9d1f46638d82326ab
--- /dev/null
+++ b/.gitlab-ci/xrdesktop_ci_signing_key_0x7C668346_public.asc
@@ -0,0 +1,52 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=802W
+-----END PGP PUBLIC KEY BLOCK-----