diff --git a/debian/control b/debian/control
index 735d78bd..bcb5bcea 100644
--- a/debian/control
+++ b/debian/control
@@ -6,6 +6,7 @@ Homepage: https://www.sipwise.com/
 Standards-Version: 3.9.8
 Build-Depends:
  asciidoctor,
+ bash-completion (>= 1:2.1-4.2~),
  debhelper-compat (= 12),
  git,
  libcapture-tiny-perl,
diff --git a/debian/ngcp-ngcpcfg.bash-completion b/debian/ngcp-ngcpcfg.bash-completion
new file mode 100644
index 00000000..f719dc05
--- /dev/null
+++ b/debian/ngcp-ngcpcfg.bash-completion
@@ -0,0 +1 @@
+debian/ngcpcfg.completion ngcpcfg
diff --git a/debian/ngcpcfg.completion b/debian/ngcpcfg.completion
new file mode 100644
index 00000000..39b39b98
--- /dev/null
+++ b/debian/ngcpcfg.completion
@@ -0,0 +1,150 @@
+# ngcpcfg(8) completion                                     -*- shell-script -*-
+
+_ngcpcfg()
+{
+    local cur prev words cword
+    _init_completion || return
+
+    case $prev in
+        apply)
+            if [[ "$cur" == -* ]]; then
+                COMPREPLY=( $( compgen -W '--force-all-services' -- "$cur" ) )
+            fi
+            return
+            ;;
+        build)
+            cur=${cur:-/etc/}
+            _filedir
+            return
+            ;;
+        check)
+            if [[ "$cur" == -* ]]; then
+                COMPREPLY=( $( compgen -W '--ignore-branch-check --ignore-shared-storage-check' -- "$cur" ) )
+            else
+                [[ -n "$cur" ]] && _filedir yml && return 0
+                COMPREPLY=( $( compgen -G "/etc/ngcp-config/*.yml" -- "$cur" ) ) || _filedir yml
+                compopt -o nospace
+            fi
+            return
+            ;;
+        clean)
+            if [[ "$cur" == -* ]]; then
+                local -a opts=(
+                  --all
+                  --branches
+                  --force
+                  --help
+                  --reset-master
+                  --stashes
+                  --tracked-files
+                  --untracked-files
+                )
+                COMPREPLY=( $( compgen -W '${opts[@]}' -- "$cur" ) )
+            else
+                _filedir
+                compopt +o nospace
+            fi
+            return
+            ;;
+        commit)
+            return
+            ;;
+        del)
+            if [[ "$cur" == -* ]]; then
+                COMPREPLY=( $( compgen -W '--diff' -- "$cur" ) )
+            fi
+            _filedir
+            compopt +o nospace
+            return
+            ;;
+        diff)
+            if [[ "$cur" == -* ]]; then
+                if [ -r /usr/share/bash-completion/completions/git ] ; then
+                    unset __git_diff_common_options
+                    . /usr/share/bash-completion/completions/git
+                    COMPREPLY=( $( compgen -W "$__git_diff_common_options" -- "$cur" ) )
+                fi
+            else
+                [[ -n "$cur" ]] && _filedir yml && return 0
+                compopt -o nospace
+            fi
+            return
+            ;;
+        get)
+            # XXX - would be nice to get completion based on content of /etc/ngcp-config/*.yml
+            return
+            ;;
+        help)
+            return
+            ;;
+        log)
+            if [[ "$cur" == -* ]]; then
+                COMPREPLY=( $( compgen -W '-p' -- "$cur" ) )
+            fi
+            return
+            ;;
+        patch)
+            if [[ "$cur" == -* ]]; then
+                COMPREPLY=( $( compgen -W '--help --from-customtt' -- "$cur" ) )
+            else
+                _filedir
+                compopt +o nospace
+            fi
+            return
+            ;;
+        pull)
+            return
+            ;;
+        push|push-parallel)
+            if [[ "$cur" == -* ]]; then
+                COMPREPLY=( $( compgen -W '--nobuild --noapply --shared-only' -- "$cur" ) )
+            else
+                _known_hosts_real -- "$cur"
+            fi
+            return
+            ;;
+        services)
+            return
+            ;;
+        set)
+            [[ -n "$cur" ]] && _filedir yml && return 0
+            COMPREPLY=( $( compgen -G "/etc/ngcp-config/*.yml" -- "$cur" ) ) || _filedir yml
+            compopt -o nospace
+            return 0
+            ;;
+        show)
+            COMPREPLY=( $( compgen -W "$(cd /etc/ngcp-config && git rev-list master --abbrev-commit 2>/dev/null)" -- "$cur" ) )
+            return
+            ;;
+        status)
+            COMPREPLY=( $( compgen -W '--local-only' -- "$cur" ) )
+            return
+            ;;
+        version)
+            return
+            ;;
+    esac
+
+    if [[ "$cur" == -* ]]; then
+        COMPREPLY=( $( compgen -W '--debug --validate --version' -- "$cur" ) )
+    else
+        if [[ $cword -eq 1 ]]; then
+            local -a scripts=( help version )  # those options don't have separate ngcpcfg scripts
+            for f in /usr/share/ngcp-ngcpcfg/scripts/* ; do
+                case "$(basename "$f")" in
+                    decrypt|encrypt|etckeeper|initialise|init-mgmt|init-shared)  # not relevant for common operations
+                        ;;
+                    values)   # deprecated options
+                        ;;
+                    *)
+                        scripts+=( $(basename "$f") )
+                        ;;
+                esac
+            done
+            COMPREPLY=( $( compgen -W '${scripts[@]}' -- "$cur" ) )
+        fi
+    fi
+} &&
+complete -F _ngcpcfg ngcpcfg ngcp-config
+
+# ex: filetype=sh
diff --git a/debian/rules b/debian/rules
index c021c031..a21e5366 100755
--- a/debian/rules
+++ b/debian/rules
@@ -9,7 +9,7 @@ SCRIPTS = \
 	$(CURDIR)/usr/sbin/ngcp-network-validator
 
 %:
-	dh $@
+	dh $@ --with=bash-completion
 
 override_dh_auto_build:
 	dh_testdir