使用reprepro+nginx搭建apt服务器

news2025/1/10 22:28:44

目录

项目背景

项目要求

项目开发过程

1、apt服务器的搭建

2、实现自定义指定源文件列表来实现apt update更新

3、实现软件启动时自动更新

4. source.list中镜像源地址的格式

项目开发的难点/坑点

总结


项目背景

       前面写过一篇“利用Nginx搭建一个apt服务器”, 但只是前期铺垫工作,只适合用于简单的场景,并没有细化,简单实现能用apt安装就可以了。现在我们来细化一下,添加一下要求,使其更加实用,适用于大型项目。

项目要求

  1. 远程服务器(实际应用会部署在阿里云上)搭建apt服务器,建立软件包管理仓库,以提高软件包下载速度,并保存有软件包仓库的地址、发行版代号、组件等信息;
  2. 本地可用apt install来安装软件;
  3. 本地可用apt update来检查是否有软件更新;
  4. 检查是否有更新或更新软件时,只涉及本apt服务器所在的源地址,不涉及其他源地址;
  5. 每当软件启动时,会自动检查更新,当有更新时自动更新;

项目开发过程

1、apt服务器的搭建

        首先需要在服务器上建立一个本地软件包镜像仓库,而建立仓库有多种手段,可以借助工具来实现,比如:apt-mirror 、repreproaptly等都是可以的,选其一即可。在此我选择了reprepro,它是一个由Debian项目提供的开源软件包管理工具,用于构建和管理Debian软件包仓库,可以帮助用户轻松地创建本地APT仓库并进行软件包的管理、发布和分发。

  • 安装reprepro

首先,在您的服务器上安装reprepro软件包管理工具。您可以使用以下命令进行安装:

$ sudo apt update

$ sudo apt install reprepro

  • 创建reprepro仓库

 创建一个目录用于存储reprepro的仓库,例如/var/www/html/apt-repository

 进入到reprepro仓库目录,并使用以下命令初始化reprepro仓库

$ mkdir /var/www/html/apt-repository

$ cd /var/www/html/apt-repository

$ mkdir conf 

$ cd conf

$ touch  distributions

distributions用于指定软件包仓库的不同发行版(distribution)的信息。

编辑distributions配置文件并添加必要的信息。您可以参考下面的示例配置文件内容:

Origin: Your_Origin     // 指定软件包仓库的来源,通常是您或您的组织的名称

Label: Your_Label       // 给软件包仓库设置一个标签,用于标识仓库

 // 每个发行版都有一个代号,比如 stabletestingunstable 等

Codename: Your_Codename 

// 指定软件包支持的架构,比如 amd64i386arm64 等

Architectures: Your_Architectures

// 指定软件包仓库的组件,比如 maincontribnon-free 等

Components: main

Description: Your_Description

// 指定用于对软件包进行签名的GPG密钥ID

SignWith: YOUR_KEY_ID   

 GPG密钥的生成:

gpg --gen-key

按照提示创建你的GPG密钥。

gpg --list-keys //显示密钥

gpg --list-keys --keyid-format LONG  //显示密钥和密钥ID

 密钥ID通常是8byte的16进制组合。

确保配置文件中的信息正确无误后,再次尝试使用以下命令初始化reprepro仓库:

$ cd /var/www/html/apt-repository

$ reprepro export

执行后,目录下应该会有以下文件生成:

$ ls

conf    db   dists    lists

现在仓库初始化完成。

  • 添加软件包到reprepro仓库

将您的软件包文件拷贝到服务器的某一目录下,例如/home/w/publish/ 。

使用以下命令将软件包添加到reprepro仓库中:

$ reprepro includedeb YourCodename /home/w/publish/package.deb

其中,YourCodename为您在配置文件中设置的Codename,当然这里也可以写软件包镜像仓库的路径,但不如写codename来的方便。

  • 发布版本

使用以下命令发布版本到reprepro仓库中:

$ reprepro export

 执行的时候会需要再次输入密钥的短语,确认后即可。

可以看一下目录架构:

$ tree

 成功后会生成一个“pool”的文件夹,存放安装包。

  • 配置Nginx

安装Nginx并配置为代理reprepro仓库的静态文件。您可以使用以下命令安装Nginx

$ sudo apt-get install nginx

编辑Nginx的配置文件/etc/nginx/sites-available/default,添加类似以下配置来代理reprepro仓库:

server {
    listen 80;

    root /var/www/html/apt-repository;
    server_name _;

    location / {
        autoindex on;
    }
}

nginx默认的路径是“/var/www/html”,将其改为仓库的路径,或者在location中使用alias命令:

location / {
        alias /var/www/html/apt-repository;
        autoindex on;
    }

保存配置文件并重启Nginx服务:

$ sudo systemctl restart nginx

  • 本地配置访问APT服务器

现在,您可以通过浏览器或者使用apt-get命令来访问您搭建的APT服务器。

在客户端的/etc/apt/sources.list文件中添加以下行来指向您的APT服务器:

deb http://192.168.2.103/ codename main

codename为您的发行版名称,main为您的软件包组。

sudo apt update

之后就可以通过

sudo apt install xxx

来安装软件了。

2、实现自定义指定源文件列表来实现apt update更新

 下面说一下实现自定义指定源文件列表来实现apt update更新,在 /etc/apt/sources.list 定义了软件源外,/etc/apt/sources.list.d 目录下的文件中也会定义一些第三方的软件源或者叫 PPA(Personal Package Archives)。如果将apt服务器的源地址写在source.list 文件中的话,每次update的时候都要将系统上所有的镜像源全都检查一遍,耗时较多,并不符合我们此次的项目的目的。如果使用软件启动时采用自检查更新的方案的话,这将会造成软件启动慢、客户体验不佳的问题。因此,单独设置apt服务器源地址是有必要的。

  1. /etc/apt/sources.list.d/目录下创建一个新的源文件,比如mirror.list,可以使用以下命令创建:

    $ sudo touch /etc/apt/sources.list.d/mirror.list

  2. 编辑这个新创建的源文件mirror.list,并添加您想要使用的镜像源地址,例如:

    deb http://your-mirror-server/ubuntu bionic main

  3. 确保mirror.list中的源地址格式正确,包括deb或者deb-src开头,并且每行只包含一个源地址。

  4. 运行 

apt update -o Dir::Etc::sourcelist=/etc/apt/sources.list.d/mirror.list

命令来更新APT,这样APT会按照mirror.list中的源地址来更新软件包信息。

3、实现软件启动时自动更新

程序启动时需要启动的脚本:

#!/bin/bash

# 执行 apt update 命令检查更新
apt update -o Dir::Etc::sourcelist=/etc/apt/sources.list.d/mirror.list > /dev/null

# 检查 apt update 命令的返回状态
if [ $? -eq 0 ]; then
    echo "检查更新成功"

    # 检查是否有可用更新
    if apt list --upgradable | grep -qE '\[upgradable\]'; then
        echo "发现可用更新,执行升级操作"
        apt upgrade -y
        echo "软件包已升级"
    else
        echo "没有可用更新"
    fi
else
    echo "检查更新失败,请检查网络连接或软件源配置"
fi

软件启动时,采用自动检查是否有更新,如果有更新,则自动更新的方案避免了用户手动更新的问题,毕竟不能要求所有用户都会使用linux系统。

4. source.list中镜像源地址的格式

  1. 源地址的格式

    • 源地址通常以debdeb-src开头,分别表示二进制软件包和源代码软件包。
    • 紧接着是软件包的下载地址,可以是HTTP、FTP等协议的URL。
    • 接下来是发行版的代号,例如Ubuntu中的版本代号(如bionic、focal等)。
    • 最后是软件包的组件,如main、restricted、universe、multiverse等。
  2. 源地址的组成

    • 主要组件(main):包含由官方团队维护的自由软件。
    • 受限组件(restricted):包含受限制的软件,不是完全自由的。
    • 宇宙组件(universe):包含社区维护的自由软件。
    • 多元宇宙组件(multiverse):包含非自由软件。

项目开发的难点/坑点

  • 问题1,将软件包文件包含进仓库的时候报错:

$ reprepro includedeb immortal /home/w/publish/benan-test-gateway_1.0.2_amd64.deb

// error

“no section given for '.deb',skipping”

“no priority given for '.deb',skipping”

        这个并不是distributions配置文件的设置问题,不要被误导,这其实是因为.deb安装包打的有问题,.deb安装包打包的时候,其control文件的设置中缺少了“section”、“priority”属性。

control 文件的属性一般如下, 

package: packagename  // 软件包的名称

version: 1.0.2  // 软件包的版本号,通常遵循特定的版本号规范,此属性必须有

architecture: amd64  // 软件包适用的架构,例如 amd64i386 等,此属性必须有

maintainer: name <email>   //软件包的维护者信息,包括姓名和邮箱地址,可不写

depends: dpkg  //软件包的运行时依赖关系,没有的话可以不写

recommends: npm,sudo // 软件包的建议性依赖关系,可不写

description: 描述信息,随便写

//软件包所属的分类,用于组织软件包在软件包管理器中的显示,此属性必须有

section: default 

// 软件包的优先级,指定软件包在安装时的优先级,此属性必须有

priority: optional 

homepage: https://xxxx/   //软件包的官方网站或主页链接,可不写

conflicts:    xxx      //软件包的冲突关系,可不写

所以,打包.deb安装包的时候尽量使用规范的写法哦。 

  • 问题2,

 W: GPG 错误:http://192.168.2.103 immortal InRelease: 由于没有公钥,无法验证下列签名: NO_PUBKEY   密钥ID

 由于apt服务器的软件包镜像仓库使用了GPG加密,该加密为非对称加密,有公钥和私钥。该问题是因为系统没有该仓库的公钥用于验证软件包的签名。所以需要将其公钥下载下来并导入本地软件包仓库。

使用下面的命令来下载公钥:

sudo apt-key adv --keyserver http://192.168.2.103 --recv-keys 密钥ID

 其中,“http://192.168.2.103” 替换成apt服务器的地址,“密钥ID”替换成真实的密钥ID。

如果不能下载的话,可以手动将密钥文件下载到本地,然后导入:

gpg --output public_key.asc --armor --export  密钥ID   //生成密钥文件

将生成的.asc公钥文件传输到本地,然后

 sudo apt-key add <public_key.asc>

然后,

sudo apt update 

就可以了。 

总结

这样的搭配才是最实用的。

动手操作才会发现更多的细节。

Talk is cheap.Show me your code.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1511907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS学习笔记-基于stm32(5)列表和列表项

一、列表与列表项简介 列表是FreeRTOS中的一种数据结构&#xff0c;类似双向循环链表。用来跟踪FreeRTOS中的任务。列表项就是存放在列表中的项目。 二、列表 列表结构体&#xff1a; typedef struct xLIST {listFIRST_LIST_INTEGRITY_CHECK_VALUE //校验值c…

闲聊电脑(7)常见故障排查

闲聊电脑&#xff08;7&#xff09;常见故障排查 夜深人静&#xff0c;万籁俱寂&#xff0c;老郭趴在电脑桌上打盹&#xff0c;桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭&#xff1a;冰箱大哥&#xff0c;平时遇到电脑故障该咋处理呢&#xff1f; 冰箱&#xf…

vscode使用svn

网上这种文章很多&#xff0c;但很多都实现不了&#xff0c;自己亲测安装有效的过程记录下来&#xff0c;分享给大家。 第一步&#xff1a;去官网下载svn.安装TortoiseSVN 下载地址 下载的地址&#xff1a; Apache Subversion Binary Packageshttps://subversion.apache.or…

55. 跳跃游戏(力扣LeetCode)

文章目录 55. 跳跃游戏贪心每一次都更新最大的步数 取最大跳跃步数&#xff08;取最大覆盖范围&#xff09; 55. 跳跃游戏 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后…

信号处理--基于Fisher分数的通道选择的多通道脑电信号情绪识别

目录 背景 亮点 环境配置 数据 方法 结果 代码获取 参考文献 背景 基于脑电的情绪分析&#xff0c;目前是当前研究的一个主要方向和热点。 亮点 使用基于Fisher score的标准来筛选具有高判别意义的脑电通道&#xff1b; 使用基于特征选择的遗传算法实现特征的筛选&#xff0c;从…

vue项目:webpack打包优化实践

本文目录 一、项目基本信息二、分析当前项目情况1、使用 webpack-bundle-analyzer 插件2、使用 speed-measure-webpack-plugin 插件 三、解决构建问题1、caniuse-lite 提示的问题2、 warning 问题 四、打包速度优化1、修改source map2、处理 loader 五、webpack性能优化1、使用…

SPI机制详解

SPI机制详解 什么是SPI机制&#xff1f; SPI&#xff1a;Service Provider Interface&#xff0c;中文直译&#xff1a;服务提供者接口&#xff0c;它通过在ClassPath路径下的META-INF/service文件夹中查找文件&#xff0c;并自动加载文件里所定义的类 在面向对象的设计原则…

Linux中文件的权限

我们首先需要明白&#xff0c;权限 用户角色 文件的权限属性 一、拥有者、所属组和other&#xff08;用户角色&#xff09; 以文件file1为例 第一个箭头所指处即是文件的拥有者&#xff0c;拥有者为zz 第二个箭头所指处即使文件的所属组&#xff0c;所属组为zz 除去拥有者…

利用高分五号02星高光谱数据进行地物识别

高分五号02星搭载了一台60公里幅宽、330谱段、30米分辨率的可见短波红外高光谱相机&#xff08;AHSI&#xff09;&#xff0c;可见近红外&#xff08;400~1000nm&#xff09;和短波红外光谱&#xff08;1000~2500nm&#xff09;分辨率分别达到5纳米和10纳米。单看参数性能优越&…

spring boot使用mybatisplus访问mysql的配置流程

网上教程大多教人新建一个带对应组件的项目&#xff0c;本文记录如何在一个已有springboot2.x项目中&#xff0c;配置使用mybatisplus来访问mysql。包括使用wrapper和自己写mapper.xml的自定义函数两种和数据库交互的方式。 关于项目的创建&#xff0c;参考创建springboot 2.x…

PFMEA的输入输出和特殊特性

DFMEA輸入&#xff1a;技术条件、市场需求 DFMEA輸出&#xff1a;产品特殊特性、试验、样件CPPFMEA輸入&#xff1a;过往经验、流程图、DPMEA PFMEA輸出&#xff1a;CP、过程特殊特性、SIP、SOP1. PFMEA的输入包括&#xff1a;&#xff08;&#xff09;过程流程图、DFMEA 、图样…

基于springboot+vue的线上教育系统(源码+论文)

目录 前言 一、功能设计 二、功能实现 三、库表设计 四、论文 前言 现在大家的生活方式正在被计算机的发展慢慢改变着&#xff0c;学习方式也逐渐由书本走向荧幕,我认为这并不是不能避免的,但说实话,现在的生活方式与以往相比有太大的改变&#xff0c;人们的娱乐方式不仅仅…

P4513 小白逛公园 习题笔记(线段树维护区间最大连续子段和)

传送门https://www.luogu.com.cn/problem/P4513本文参考了董晓老师的博客 这道题着实想了很长时间&#xff08;新手&#xff09;&#xff0c;只能想到一个O&#xff08;mn&#xff09;的dp普通写法&#xff0c;那么遇上区间修改问题改怎么操作呢。答案很明显&#xff0c;线段树…

微服务day01 -- SpringCloud01 -- (Eureka , Ribbon , Nacos)

介绍微服务 1.认识微服务(p1-p5) 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的稻田虫害检测系统详解(深度学习+Python代码+UI界面+训练数据集)

摘要&#xff1a;本篇文章深入探讨了如何利用深度学习技术开发一个用于检测稻田虫害的系统&#xff0c;并且分享了完整的实现过程和资源代码下载。该系统采用了当前的YOLOv8、YOLOv7、YOLOv6、YOLOv5算法&#xff0c;对其进行了性能对比&#xff0c;包括mAP、F1 Score等关键指标…

redis中通用命令以及key过期策略

通用命令 exists 判断某个key是否存在。 exists key时间复杂度&#xff1a;O(1) 返回值&#xff1a;key 存在的个数。 del 删除指定的 key&#xff0c;可以一次删除一个或者多个。 del key时间复杂度&#xff1a;O(1) 返回值&#xff1a;删除掉的 key 的个数。 expire…

根据索引策略对elasticsearch中的索引进行管理(附带图文教程)

前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 一. 索引生命周期简介 想要了解更多可以看 &#xff1a; 索引生命周期 1.1 索引生命周期五种阶段 &#xff08;1&#xff09;Hot…

C++开发基础——类模板

一&#xff0c;基础定义 类模板是用来生成类的蓝图&#xff0c;是一种创建类的方式&#xff0c;同一套类模板可以生成很多种不同的类。 编译器基于类模板生成的每个类被称为类模板的实例。 第一次使用模板类型声明变量时&#xff0c;会创建类模板的一个实例&#xff0c; 以后…

YOLOv5改进 | 注意力篇 | 利用YOLO-Face提出的SEAM注意力机制优化物体遮挡检测(附代码 + 修改教程)

一、本文介绍 本文给大家带来的改进机制是由YOLO-Face提出能够改善物体遮挡检测的注意力机制SEAM&#xff0c;SEAM&#xff08;Spatially Enhanced Attention Module&#xff09;注意力网络模块旨在补偿被遮挡面部的响应损失&#xff0c;通过增强未遮挡面部的响应来实现这一目…

el-Switch 开关二次确认

前言 最近在做毕设&#xff0c;有个需求是点击按钮控制用户的状态是否禁用&#xff0c;就看到element有个switch组件可以改造一下&#xff0c;就上网看了一下&#xff0c;结果为了这个效果忙活了很久。。。所以说记录一下&#xff0c;让大家少踩坑。 前置条件 先看完我的需求再…