Skip to content

Packaging a VUE project into a Debian package and automatic Nginx configuration ​

Diagram of postrm script cleanup logic and purge pitfalls

In the previous chapter, we packaged the Golang backend project into a standard Debian package. This chapter will shift the perspective to Frontend, package a VUE project as .deb package, and implement automated integration with Nginx.

Unlike backend packaging, the focus of packaging a VUE project is on:

  • Static Asset Deployment: will dist Deploy the directory to the correct location.

  • Nginx Configuration Management: Automatically configure Nginx sites to enable frontend-backend joint debugging

  • Stateless cleanup:remove and purge The difference is relatively simple.

Overall Solution Overview ​

VUE build vs Golang build ​

Comparison dimensionGolang backendVUE frontend
Package contentsbinary file + systemd serviceStatic resources (HTML/CSS/JS) + Nginx configuration
Core dependencysystemdnginx
postinst responsibilitiesStart serviceReload Nginx
Is prerm required?✅ Required (stop service)❌ Usually not required (stateless)
postrm responsibilitiesClean up systemd remnantsClean up deployment directory + restore Nginx configuration

Final deliverable ​

out/debian/cms-manager-1.7.0-amd64.deb

this .deb Package includes:

  • ✅ VUE project build artifacts (dist/ Table of Contents)

  • ✅ Nginx site configuration file

  • ✅ postinst / postrm maintainer scripts

Project directory structure ​

text
<cms-manager>/
├── docker/
│   └── debian/
│       ├── builder.Dockerfile          # Docker build file
│       ├── dist/ -> ../../dist         # Build artifact symlink
│       ├── nginx/ -> ../../nginx/debian # Nginx configuration symlink
│       └── scripts/
│           ├── postinst                 # post-install script
│           └── postrm                   # post-uninstall script
├── dist/                               # VUE build artifacts
│   ├── index.html
│   └── assets/
├── nginx/
│   └── debian/
│       └── cms-manager.nginx.conf      # Nginx site configuration
├── .dockerignore
└── Makefile

📌Naming convention: This paper takes cms-manager As an example project name, you can replace it with the actual project name.

Step 1: Create the directory structure ​

bash
# Create Debian packaging build directory
mkdir -p docker/debian

# Enter the directory
cd docker/debian

Step 2: Configure the Nginx site ​

bash
# Execute in the docker/debian directory
ln -s ../../nginx/debian ./nginx

Nginx site configuration file ​

Create nginx/debian/cms-manager.nginx.conf:

nginx
server {
    listen       80;
    listen       [::]:80;
    server_name  cms.server;

    # VUE project static assets
    location / {
        try_files $uri $uri/ @router;
        root   /var/www/html/cms-manager/dist;
        index  index.html;
    }

    # Proxy backend API interface
    location /api/ {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:9400/v1/api/;
    }

    # Proxy backend static resources
    location /resource/ {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:9400/static/;
    }

    # Proxy WebSocket interface
    location /websocket/ {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection Upgrade;
        proxy_set_header Upgrade websocket;
        proxy_pass http://127.0.0.1:9400/v1/websocket/;
    }

    # Fix the 404 issue when refreshing SPA routes
    location @router {
        rewrite ^.*$ /index.html last;
    }
}

💡Key points:try_files $uri $uri/ @router and location @router It is the core configuration of VUE/React SPA applications, solving the 404 issue when frontend routes are refreshed.

Step 3: Build the artifact directory ​

bash
# Execute in the docker/debian directory
ln -s ../../dist ./dist

⚠️Important: Before running the Docker build,Must be executed first.npm run build Generate dist Table of contents.

Step 4: Maintainer Script ​

Unlike backend services, the maintainer scripts of frontend projects No need prerm(Because static resources do not need to be "stopped"), only need postinst and postrm.

postinst (post-installation script) ​

bash
#!/bin/sh
set -e

log() {
    logger -t "cms-manager-postinst" "$@"
}

case "$1" in
    configure)
        log "Starting cms-manager configuration"

        # 1. Set dist directory permissions
        DIST_DIR="/var/www/html/cms-manager/dist"
        if [ -d "$DIST_DIR" ]; then
            log "Setting $DIST_DIR permissions to 755"
            chmod 755 "$DIST_DIR" || {
                log "Failed to set $DIST_DIR permissions"
                exit 1
            }
        else
            log "$DIST_DIR does not exist, skipping permission setup"
        fi

        # 2. Reload Nginx (gracefully takes effect)
        log "Attempting to reload nginx"
        if command -v systemctl >/dev/null 2>&1; then
            if systemctl is-active --quiet nginx; then
                systemctl reload nginx && log "nginx reloaded successfully" || {
                    log "Failed to reload nginx"
                    exit 1
                }
            else
                log "nginx is not running, skipping reload"
            fi
        elif command -v service >/dev/null 2>&1; then
            service nginx reload && log "nginx reloaded successfully" || {
                log "Failed to reload nginx"
                exit 1
            }
        else
            nginx -s reload && log "nginx reloaded successfully" || {
                log "Failed to reload nginx"
                exit 1
            }
        fi

        log "cms-manager configuration completed"
        ;;
    *)
        log "Unknown operation: $1"
        ;;
esac

exit 0

postrm (post-removal script) ​

bash
#!/bin/bash
set -e

case "$1" in
  remove|purge)
    echo "[cms-manager] Removing /etc/nginx/sites-enabled/default and restoring soft link..." >&2

    # 1. Delete the current default configuration (overridden by this package)
    if [ -e /etc/nginx/sites-enabled/default ]; then
      rm -f /etc/nginx/sites-enabled/default
    fi

    # 2. Delete the deployment directory
    if [ -e /var/www/html/cms-manager ]; then
      rm -rf /var/www/html/cms-manager
    fi

    # 3. Restore the system default Nginx configuration
    if [ -f /etc/nginx/sites-available/default ]; then
      ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
      echo "[cms-manager] Default soft link restored" >&2
    fi

    # 4. Reload Nginx
    if command -v systemctl >/dev/null 2>&1; then
      systemctl reload nginx || true
    elif command -v service >/dev/null 2>&1; then
      service nginx reload || true
    else
      nginx -s reload || true
    fi
    ;;
  upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
    # No action needed
    ;;
  *)
    echo "postrm called with unknown argument \`$1'" >&2
    exit 1
    ;;
esac

exit 0

⚠️Note:postrm What we operate in is /etc/nginx/sites-enabled/default, this means Each server can only deploy one frontend project. If you need to deploy multiple frontend projects on the same server, you should use separate configuration files (such as sites-available/cms-manager.conf), rather than overwrite default.

Step 5: Docker build file (builder.Dockerfile) ​

Similar to the Golang version, VUE packaging also uses a multi-stage Docker build, but Only the packaging stage(Because VUE builds are usually completed on the host machine or in CI).

dockerfile
# ============================================================
# Global build parameters
# ============================================================
ARG VERSION
ARG APPNAME=cms-manager

# ============================================================
# Stage: Debian packaging environment
# ============================================================
FROM ubuntu:20.04

ARG VERSION
ARG APPNAME

ENV VERSION=$VERSION
ENV APPNAME=$APPNAME
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Shanghai

# Configure a domestic mirror source
RUN sed -i \
    -e 's|http://.*archive.ubuntu.com|http://mirrors.aliyun.com|g' \
    -e 's|http://.*security.ubuntu.com|http://mirrors.aliyun.com|g' \
    /etc/apt/sources.list

# Configure time zone
RUN apt-get update && \
    apt-get install -y --no-install-recommends tzdata && \
    ln -fs /usr/share/zoneinfo/$TZ /etc/localtime && \
    dpkg-reconfigure --frontend noninteractive tzdata

# Install packaging tool
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        dpkg-dev \
        ca-certificates \
        curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /workspace

# Copy the Nginx configuration file (overwrite default)
COPY docker/debian/nginx/${APPNAME}.nginx.conf /etc/nginx/sites-enabled/default
RUN chmod 644 /etc/nginx/sites-enabled/default

# Copy VUE build artifacts
COPY docker/debian/dist /var/www/html/${APPNAME}/dist
RUN chmod -R 755 /var/www/html/${APPNAME}/dist

# Copy maintainer script
COPY docker/debian/scripts/postinst docker/debian/scripts/postrm /tmp/
RUN chmod +x /tmp/postinst /tmp/postrm

# ============================================================
# Build Debian package directory structure
# ============================================================
RUN mkdir -p package && \
    # Nginx configuration
    mkdir -p package/etc/nginx/sites-enabled/ && \
    cp /etc/nginx/sites-enabled/default package/etc/nginx/sites-enabled/ && \
    # VUE static assets
    mkdir -p package/var/www/html/${APPNAME}/ && \
    cp -r /var/www/html/${APPNAME}/dist package/var/www/html/${APPNAME}/ && \
    # Maintainer script
    mkdir -p package/DEBIAN && \
    mv /tmp/postinst package/DEBIAN/ && \
    mv /tmp/postrm package/DEBIAN/

# Generate the control file
RUN echo "Package: ${APPNAME}" > package/DEBIAN/control && \
    echo "Version: ${VERSION}" >> package/DEBIAN/control && \
    echo "Architecture: amd64" >> package/DEBIAN/control && \
    echo "Maintainer: Applyfly <[email protected]>" >> package/DEBIAN/control && \
    echo "Description: A ${APPNAME} VUE3 Debian package" >> package/DEBIAN/control && \
    echo "Installed-Size: $(du -s package/var/ | cut -f1)" >> package/DEBIAN/control && \
    echo "Size: $(du -s package | cut -f1)" >> package/DEBIAN/control && \
    echo "Depends: nginx" >> package/DEBIAN/control && \
    echo "Pre-Depends: debconf" >> package/DEBIAN/control && \
    echo "Section: utils" >> package/DEBIAN/control && \
    echo "Priority: optional" >> package/DEBIAN/control

# Package
RUN dpkg-deb --build package && \
    mv package.deb /${APPNAME}-${VERSION}-amd64.deb

# Output
VOLUME /workspace
CMD ["sh", "-c", "cp /${APPNAME}-${VERSION}-amd64.deb /output/"]

Dockerfile Key Points Explained ​

StepsOperationExplanation
Configuration sourceReplace with the Alibaba Cloud mirrorSpeed up apt package downloads
Time zone settingsTZ=Asia/ShanghaiEnsure the log time is correct.
Installation toolsdpkg-devProvide dpkg-deb Packaging command
Copy configurationCoverage defaultPlace the Nginx configuration in sites-enabled
Copy static assetsdist/→/var/www/html/Deploy to the standard web directory
Packdpkg-deb --buildGenerate a .deb file

Step 6: .dockerignore ​

txt
.git
*.md
tmp/
node_modules
out

💡Note:node_modules Must be excluded, otherwise it will significantly increase the build context size.

Step 7: Makefile automated build ​

makefile
OUTPUT_DIR ?= ./out

.PHONY: builder-debian

builder-debian:
ifndef VERSION
	$(error VERSION is required. Usage: make builder-debian VERSION=1.7.0)
endif
	@echo "Building Debian package..."
	@mkdir -p $(OUTPUT_DIR)/debian
	DOCKER_BUILDKIT=1 docker build \
		-f docker/debian/builder.Dockerfile \
		-t cms-manager-builder:$(VERSION) \
		--build-arg VERSION=$(VERSION) \
		.
	@docker run --rm -v $(abspath $(OUTPUT_DIR)/debian):/output cms-manager-builder:$(VERSION)
	@echo "Package built: $(OUTPUT_DIR)/debian/cms-manager-$(VERSION)-amd64.deb"

Execute build ​

bash
# Build the VUE project first
npm run build

# Then package it as a Debian package.
make builder-debian VERSION=1.7.0

⚠️Attention: Building VUE does not require an SSH agent (unlike Golang, which requires pulling private repositories), so it is omitted in the Makefile.ssh-agent Related commands.

Step 8: Deployment and Verification ​

Upload to the server ​

bash
scp out/debian/cms-manager-1.7.0-amd64.deb username@host:/tmp/

Install the software package ​

bash
# Use apt (recommended)
sudo apt install /tmp/cms-manager-1.7.0-amd64.deb

# or use dpkg
sudo dpkg -i /tmp/cms-manager-1.7.0-amd64.deb

Verify deployment ​

bash
# Check whether the file is deployed successfully
ls -la /var/www/html/cms-manager/dist/

# Check Nginx configuration
cat /etc/nginx/sites-enabled/default

# Reload Nginx (postinst has already been executed automatically)
systemctl status nginx

# Access test
curl http://localhost/

View postinst log ​

bash
# postinst uses logger to log
tail -f /var/log/syslog | grep cms-manager

Uninstall and Cleanup ​

Normal uninstall (keep configuration) ​

bash
sudo apt remove cms-manager

Execute remove when,postrm Will:

  • Delete /var/www/html/cms-manager/ Contents

  • Restore the default Nginx configuration

  • Reload Nginx

Completely remove ​

bash
sudo apt purge cms-manager

purge and remove Behavior in front-end projects Basically consistent(Because there are no configuration files that require extra cleanup.)

Common troubleshooting ​

Question 1: Accessing the page after installation returns 404 ​

bash
# Check if the dist directory exists
ls -la /var/www/html/cms-manager/dist/

# Check whether the Nginx configuration is correct
nginx -t

# View Nginx error logs
tail -f /var/log/nginx/error.log

Problem 2: Nginx reload failed ​

bash
# Check Nginx configuration syntax
nginx -t

# View detailed error
systemctl status nginx -l

Issue 3: 404 on frontend route refresh ​

Check whether the Nginx configuration contains:

nginx
location / {
    try_files $uri $uri/ @router;
}

location @router {
    rewrite ^.*$ /index.html last;
}

Issue 4: Conflicts among multiple frontend projects ​

If you need to deploy multiple frontend projects on the same server,Should not be overwritten default Configuration, but should use a separate configuration file:

nginx
# /etc/nginx/sites-available/cms-manager.conf
server {
    listen 80;
    server_name cms.example.com;
    # ...
}

Then create a symbolic link:

bash
ln -s /etc/nginx/sites-available/cms-manager.conf /etc/nginx/sites-enabled/

VUE vs Golang Packaging Comparison Summary ​

Comparison dimensionGolang backendVUE frontend
Core deliverablebinary fileStatic assets (dist/)
Service Managementsystemd serviceNginx site configuration
postinst responsibilitiesEnable service + StartSet permissions + reload Nginx
Is prerm required?✅ Required (stop service)❌ Not needed
postrm responsibilitiesClean up systemd remnantsClean up deployment directory + restore Nginx
dependency packagesystemdnginx
Build toolgo buildnpm run build

Summary ​

In this chapter, you packaged a Vue front-end project into a standard Debian package, achieving:

GoalImplementation method
✅ Static resource deploymentCopy dist/ to /var/www/html/
✅ Nginx Auto ConfigurationCoverage /etc/nginx/sites-enabled/default
✅ Automatically takes effect after installationpostinst reloads Nginx
✅ Automatically clean up on uninstallpostrm delete deployment directory + restore configuration
✅ Standardized deliveryOutput .deb package, supports apt/dpkg management

Special Topic Summary ​

With this, all six articles in the Debian packaging series are now complete:

ChapterCore content
Chapter ZeroDebian Packaging Primer: control, rules, changelog
Chapter 1Complete Interpretation and Best Practices of the postinst Script
Chapter 2The role of the prerm script and how to use it correctly
Chapter 3Cleanup Logic in the postrm Script and the purge Pitfall
Chapter 4Complete Guide to Packaging a Golang Project as a Debian Package
Chapter 5Packaging a VUE project as a Debian package with automatic Nginx configuration

From the theoretical foundations of maintainer scripts to hands-on packaging of backend services and frontend static assets, this series covers Debian packaging's Complete knowledge system. I hope this guide can help you build standardized, stable, and maintainable Debian packages in real projects.

最后更新2026/11/07 14:16
如果你觉得这篇文章有帮助,或者想聊聊技术、工作,欢迎通过下面方式联系我:
contact fishfinal