vaultwarden密码库 搭建流程

Posted 歪果仨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vaultwarden密码库 搭建流程相关的知识,希望对你有一定的参考价值。

系统工程 - 建设篇

第二章 vaultwarden密码库 搭建流程


系列文章回顾

第一章 宝塔面板+NextCloud文档云 搭建流程


前言

建设安全可存储的密码库,以开源版bitwarden为例,方便IT人员安全存储密码
由于BitWarden是一个网站应用,是B/S架构,而且支持docker部署,所以需要搭建一台支持docker部署的Linux,同时为了方便管理Linux服务器,在Linux服务器上使用宝塔运维面板进行运维管理。


前置条件

  • Linux虚拟机已安装LNMP
  • Linux虚拟机需要联网
  • 准备Xshell等连接工具,安装lrzsz、zip、unzip等工具

实施步骤

1. 宝塔面板配置docker,开启docker服务
2. 从docker.io镜像库下载vaultbitwarden版本,运行镜像并测试访问密码库后台
3. 配置密码库的基础功能、组织、管理员
4. Chrome、Firefox浏览器安装bitwarden插件,测试登录和自动填充功能


注意事项

  1. 如果vaultwarden使用的SSL证书是自建CA的SSL证书,那么浏览器就需要导入自建CA证书才可正常访问登录bitwarden,否则会提示证书告警并登录失败。

浏览器插件下载链接

Chrome bitwarden
Firefox bitwarden



部署 vaultwarden密码库

宝塔面板配置docker,开启docker服务

宝塔网站管理





从docker.io镜像库下载vaultbitwarden版本,运行镜像并测试访问密码库后台

镜像下载的可选方式:
① 登录nginx后台,使用docker pull命令下载

# Linux后台
[root@localhost ~]# cd /opt
[root@localhost ~]# docker pull vaultwarden/server:latest

② 登录宝塔面板,使用宝塔提供的docker镜像窗口下载


docker run运行镜像

# Linux后台
# 必须用命令行执行docker run      CLI命令可以更简单地执行丰富的参数集

docker run -d --restart=always --name vaultwarden -v /www/wwwroot/vaultwarden/:/data/ -p 8000:80 \\
-e LOG_FILE=data/access.log \\
-e LOG_LEVEL=info \\
-e EXTENDED_LOGGING=true vaultwarden/server:latest

# 上述参数解析:   -d --detach  后台运行容器并打印容器ID        --name  指定容器名称       -v --volume  指定映射的目标 (本地:容器)     -p --publish  指定映射的端口号 (本地:容器)
#                -e --env     设置容器运行的环境变量, 一般用来设置容器内软件的参数和配置.

宝塔面板部署vaultwarden密码库网站,伪静态+SSL证书

SSL证书的添加过程(略)

# 伪静态配置
location / 
  proxy_pass http://vaultwarden.xxx.com:8000;

# nginx配置文件
server

    listen 80;
	listen 443 ssl http2;
    server_name vaultwarden.xxx.com;
    index index.php index.html index.htm default.php default.htm default.html;
    root /www/wwwroot/vaultwarden/;

    #HTTP_TO_HTTPS_START
    if ($server_port !~ 443)
        rewrite ^(/.*)$ https://$host$1 permanent;
    
    #HTTP_TO_HTTPS_END
    ssl_certificate    /www/server/panel/vhost/cert/vaultwarden.xxx.com/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/vaultwarden.xxx.com/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=31536000";
    error_page 497  https://$host$request_uri;
		#SSL-END

    #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
    include /www/server/panel/vhost/rewrite/vaultwarden.xxx.com.conf;
    #REWRITE-END
    
    access_log  /www/wwwlogs/vaultwarden.xxx.com.log;
    error_log  /www/wwwlogs/vaultwarden.xxx.com.error.log;



测试访问密码库的首页和后台

访问https://vaultwarden.xxx.com/


访问密码库后台并配置后台参数

# Linux后台
docker run -d --restart=always --name vaultwarden -v /www/wwwroot/vaultwarden/:/data/ -p 8000:80 \\
-e LOG_FILE=data/access.log \\
-e LOG_LEVEL=info \\
-e EXTENDED_LOGGING=true \\
-e ADMIN_TOKEN=random_token_as_this_server_above_admin_pass \\			# 删除docker容器,重新执行docker run并添加ADMIN_TOKEN参数,开放密码库后台的访问
vaultwarden/server:latest

访问https://vaultwarden.xxx.com/admin/

配置完成后台参数后,在后台将ADMIN_TOKEN设置成空,退出即关闭后台界面访问



配置密码库的基础功能、组织、管理员

(略)



Chrome、Firefox浏览器安装bitwarden插件,测试登录和自动填充功能

安装过程(略)

测试登录和自动填充








参考来源

  1. 宝塔社区版本
  2. 自建bitwarden/vaultwarden的密码服务
  3. Docker部署Vaultwarden(Bitwarden_RS)

如何搭建组件库的最小原型


写作背景:

     现在其实做的不错的开源 UI 库有很多,我还没有真正的实践过多造一个轮子也没太大必要,但是学习编写的思路和过程还是很有必要的,正好看到慕课的一个视频就顺便总结一下组件库开发的流程,顺便熟悉一个打包的配置和流程。

搭建基础结构:

使用VueCli创建默认模板:

  1. 创建名为it200-ui的项目:vue create it200-ui
  2. 使用默认Vue2模板即可,我们只考虑搭建UI库的思路不考虑版本的选择;
  3. 按提示命令进入项目cd it200-ui,并启动yarn serve

调整目录使适合UI库开发:

  1. 调整src/components层级到根目录;
  2. 调整src为组件渲染示例examples
  3. 通过在 vue.config.js 配置pages节点来更改入口;

创建第一个演示组件:

     目录结构如下,需按要求安装开发依赖sass-loader,为了避免与 node-sass 的版本冲突造成得更多问题,我们不再安装它而去添加一个名为sass包;

components
├─lib
|  ├─demo
|  |  └index.vue
├─css
|  └demo.scss

在示例文件夹得 main.js 中导入并申明组件:

import "../components/css/demo.scss";
import Demo from "../components/lib/demo/index.vue";
Vue.component("name", Demo);

创建组件安装脚本:

     通常在使用开源 UI 库时并没有使用 component 来导入组件,而是使用的 use 进行安装,所以我们在组件的同目录创建一个组件的安装脚本:

import Demo from "./index.vue";

Demo.install = function (Vue) 
  Vue.component(Demo.name, Demo);
;

export default Demo;

使用组件安装脚本注册组件:

import Demo from "../components/lib/demo/index.js";
Vue.use(Demo);

开发一个组件的生命周期:

设计组件:

     组件的设计一定是为了满足多处的复用而提出来的,站在各自的角度也可能都会有不一样的答案,所以我们这里找了 Elementcard 组件中的一块内容来充当我们今天待设计组件的需求:

组件设计稿:

卡片组件需要满足以下几点要求,其他的要求暂不考虑:

  1. 支持通过 body-style 属性来覆盖默认的 body 区域属性;
  2. 支持通过 shadow 属性来设置阴影出现的时机;

组件提供的属性:

参数 说明 类型 可选值 默认值
body-style 设置 body 的样式 object padding: 20px
shadow 设置阴影显示时机 string always / hover / never always

编写组件模板:

创建card 组件的结构:

components/
├─lib
|  ├─card
|  |  ├─index.js
|  |  └index.vue
├─css
|  └card.scss

注册并在 App.vue 中使用组件:

import "../components/css/card.scss";
import Card from "../components/lib/card/index.js";
Vue.use(Card);

按设计要求为组件添加属性:

通过 props 提供组件的上述基础属性。

export default 
  name: "it-card",
  props: 
    bodyStyle: 
      type: Object,
      default: () => 
        return  padding: "20px" ;
      ,
    ,
    shadow: 
      type: String,
      default: "always",
    ,
  ,
;

编写组件模板的框架:

     组件的大致结构如下,通过三层 div 来设置卡片组件容器、阴影、内容区的样式,并提供默认插槽来设置具体内容。

<template>
  <div class="it-card">
    <div :class="`is-$shadow-shadow`"></div>
    <div class="it-card__body" :style="bodyStyle">
      <slot></slot>
    </div>
  </div>
</template>

编写组件的样式:

.it-card 
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  transition: 0.3s;
  .it-card__body 
    padding: 20px;
  
  .is-always-shadow 
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
  
  .is-hover-shadow:hover 
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
  
  .is-never-shadow 
    box-shadow: none;
  

在 App.vue 中完善卡片组件:

在 app.vue 中完善卡片组件,并对比组件设计稿。

<template>
  <div id="app">
    <h3>Card组件</h3>
    <it-card style="width: 300px" :body-style=" padding: 0px ">
      <img
        src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
        class="image"
      />
      <div style="padding: 14px">
        <span>好吃的汉堡</span>
        <div class="bottom">
          <time class="time">"2022-05-03T16:21:26.010Z"</time>
        </div>
      </div>
    </it-card>
  </div>
</template>

<script>
export default 
  name: "App",
;
</script>

<style>
// 这里的样式使用 element card 使用的样式
</style>

构建 UMD 模块:

在前端模块化的进程中,经过了全局函数、命名空间,匿名函数自调,文件模块化方案,尤为常见的文件模块化方案就是 CommonJs,ADM,UMD 了,下面来介绍一下各自的特点;

CommonJs:

  1. 文件作用域:每个文件即为一个单独的模块,模块中的内容未主动暴露则对外不可见;
  2. 缓存:模块的加载只发生在第一次导入,在之后的导入会优先读取缓存;
  3. 同步加载:同步加载能保证在使用是必定存在该模块,但是并不适用于浏览器端,当同步加载慢的时候可能造成浏览器假死的状态发生。

结论:CommonJs 的模块更适用于服务端应用。

AMD:

  1. 文件作用域:同 CommonJs,也是模块化的主要产物;
  2. 异步加载:异步加载更好的适用于浏览器端,可以在异步加载后通过回调来执行后续的脚本。

结论:AMD 的模块更适用于浏览器端应用。

UMD通用模块:

  1. 同时满足适用于浏览器和服务端的模块化解决方案;
  2. 通过判断是否包含 exports 来确认是否支持 Node.js 模块;
  3. 通过判断是否包含 define 来确认是否支持 AMD 模块;
  4. 上述两个特点均不存在则将模块挂在到全局(windowglobal)。

    使用 Webpack 来打包组件逻辑代码:

    定义 webpack 打包配置文件webpack.components.js

  5. 组件的打包我们使用多入口的方式分别处理,所以我们首先处理入口,通过遍历组件 lib 目录来得到一个以组件名和组件路径组成的键值对。
    
    const glob = require("glob");

let entrys = ;

async function makrList(dirPath, list)
const files = glob.sync($dirPath/**/index.js);
for (let file of files)
const component = file.split(/[/.]/)[2];
list[component] = ./$file;

makrList("components/lib", entrys);


2. 接下来我们处理出口的配置:
   1. 输出文件名称:使用入口的 key 来区分各个组件,并使用通过的 umd 作为组件输出产物的标识;
   1. 输出目录:这里需要注意使用绝对路径来指定输出文件的位置;
   1. libraryTarget和library有相互依赖的关系,主要用来指定模块的暴露方式和模块的别名,这一块的描述我觉得 Rollup 中的描述将更清晰。
```javascript
const path = require("path");

module.exports = 
  entry: entrys,
  output: 
    filename: "[name].umd.js",
    path: path.resolve(__dirname, "dist"),
    library: "it200",
    libraryTarget: "umd",
  ,
;
  1. 最关键的是我们的 webpack 默认不认识.vue 的文件我们需要使用对应的loader来处理,Vue 文件对应的就是vue-loader,需要注意的是我们目前基于 Vue2 来构建的项目,所以最新的vue-loader并不是特别适合我们可以降级到 **15** 版本来让构建正常进行。
    
    const  VueLoaderPlugin  = require("vue-loader");

module.exports =
plugins: [new VueLoaderPlugin()],
module:
rules: [

test: /.vue$/,
use: [

loader: "vue-loader",
,
],
,
],
,
;


4. 为了方便调用我们还是配置一下打包命令:
```javascript
"build:js": "webpack --config ./webpack.components.js"

为了满足全部导入的要求,我们还需要将组件整合:

在 lib 目录下新建一个index.js 文件将我们的组件统一导入后统一执行组件挂载。

import Demo from "./demo";
import Card from "./card";

const components = 
  Demo,
  Card,
;

const install = function (Vue) 
  if (install.installed) return;
  Object.keys(components).forEach((key) => 
    Vue.component(components[key].name, components[key]);
  );
;

export default 
  install,
;

使用Gulp 来打包组件的样式代码:

gulp 主要通过定义任务并使用流式的处理方式使用不同的管道依次进行,我们主要处理 scss 文件内容为 css 文件。

需要用到的模块如下:

  1. gulp-sass,因版本问题需要额外导入 sass 模块。
  2. gulp-minify-css:主要用来对 css 文件进行压缩。

完整的打包配置如下:

  1. 配置文件指明了操作的文件入口为css 目录下的 scss 结尾的文件;
  2. 文件输出到 dist/css 目录下;
  3. 方便执行我们配一下打包命令:"build:css": "npx gulp sass"
    
    const gulp = require("gulp");
    const sass = require("gulp-sass")(require("sass"));
    const minifyCSS = require("gulp-minify-css");

gulp.task("sass", async function ()
return gulp
.src("components/css/*/.scss")
.pipe(sass())
.pipe(minifyCSS())
.pipe(gulp.dest("dist/css"));
);

#### 将模块化的 scss 文件整合到一起,方便全部加载:
在 css 目录新建 index.scss 文件,并将各个组件需要的 scss 文件导入到此文件。
```css
@import "./card.scss";
@import "./demo.scss";

按需引入和全部引入:

import "../dist/css/index.css";
import IT200UI from "../dist/index.umd";
Vue.use(IT200UI);
import "../dist/css/card.css";
import Card from "../dist/card.umd";
Vue.use(Card);

import "../dist/css/demo.css";
import Demo from "../dist/demo.umd";
Vue.use(Demo);

发布组件库到 NPM:

  1. 注册 npm 用户;
  2. 调整 package.json ;

    调整 package:

  3. 移除私有配置:private;
  4. 添加组件库描述信息:description;
  5. 添加组件入口文件:main;
  6. 添加组件相关的关键词:keywords;
  7. 添加作者名字:author;
  8. 添加组件库发布的内容:files;

完成新增内容如下:


  "description": "IT200 组件库,最小原型演示",
  "main": "dist/index.umd.js",
  "keywords": [
    "it200",
    "ui",
    "组件库"
  ],
  "author": "fe-xiaoxin",
  "files": [
    "dist",
    "components"
  ]

调整组件库的说明文档:

  1. 包含组件库的安装方式;

  2. 包含组件库的引用方式;

快速开始

如何安装
npm i it200-ui
如何引入
// 全部引入
import it200-ui/dist/css/index.css;
import IT200UI from it200-ui;
Vue.use(IT200UI);

// 按需引入
import it200-ui/dist/css/cart.css;
import  Card  from it200-ui;
Vue.use(Card);

正式开始发布:

  1. 确认 NPM 源为修改成其他镜像地址,我这里使用 nrm 包进行源的管理,可以通过 nrm ls查询和 nrm use 进行切换;
  2. 执行 npm login 开始登陆,分别输入用户名、密码、邮箱,开通动态验证的话还需要输入动态验证码,开通的方式可以翻我以前的文章;
  3. 执行 npm publish 开始发布,开通动态验证码的话需要再次验证动态验证码;

写到最后:

     整个组件库的开发我们省略了最后一步,因为版本的问题导致 vuepress 没有成功的配置,在开发组件库的过程中使用到的技术栈可以是五花八门但是通过本次总结到的我们开发组件库的生命周期大致统一应该是搭建结构、设计组件、编写组件、验证组件、打包构建、发布为主线,构建组件库文档站点、编写使用手册、自动化构建发布为支线同步进行。

以上是关于vaultwarden密码库 搭建流程的主要内容,如果未能解决你的问题,请参考以下文章

linux运维工程师一般做了哪些方面的工作?

Nginx 上的 Vaultwarden 可以通过 IP 地址访问,但不能通过域名访问

Linux运维发展方向及系统运维技能

centos 搭建SVN服务器简单流程

项目案例第二篇中小型公司优化性能安全篇

Web安全篇学习笔记3