配置docker-compose.yml

services:
  kanboard:
    image: kanboard/kanboard:latest
    ports:
      - "800:80"
      - "4433:443"
    volumes:
      - kanboard_data:/var/www/app/data
      - kanboard_plugins:/var/www/app/plugins
      - kanboard_ssl:/etc/nginx/ssl
volumes:
  kanboard_data:
  kanboard_plugins:
  kanboard_ssl:

配置nginx

cd /etc/nginx/sites-available
sudo nano kanboard
server {
    listen 80;
    server_name kanboard.kipjay.org;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name kanboard.kipjay.org;

    ssl_certificate /etc/letsencrypt/live/kipjay.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/kipjay.org/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    location / {
        proxy_pass http://127.0.0.1:800/;
        proxy_set_header Host $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;
    }
}
sudo ln -s /etc/nginx/sites-available/kanboard  /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

在cloudflare配置DNS记录

A记录;开启cloudflare代理;输入IP;输入子域名前缀;输入备注(服务名称,搭建在什么服务器上)

第三方CSS样式

https://kanboard.kipjay.org/settings/application

#tasklist li {
  border-radius: 10px;
  border: 1px solid #DEDEDE;
}

.task-middle {
  font-size: 14px;
  line-height: 25px;
}

.task-listname { margin-right: 4px; }

.h2 {
  color: rgba(175, 47, 47, 0.31);
  font-size: 22px;
  font-weight: 100;
  text-align: center;
}

.h3 {
  border-bottom: 0px;
}

a { color: black; }

/* ##################  * BOARD TWEAKING  * ################## */
#board {
  border-top: 0px solid #CCC;
  border-right: 0px solid #CCC;
}

.board-swimlane > td {
  border-top: 1px solid #CCC;
  border-right: 1px solid #CCC;
}

[class^="board-swimlane-columns-"]{
  /* display: none;*/ // This will hide column names above board/swimlanes
}

.board-swimlane-columns-0 { display: table-row; }
.board-swimlane-columns-0 > .board-column-header {
  /*font-size: 13px;*/
  border-bottom: 0px solid #c7c7c7;
}

#board-container table, #board-container tr {
  border-collapse: separate;
  border-spacing: 15px 0;
  border: 0px solid #CCC;
}

#board-container td {
  padding: 5px 0;
  border: 1px solid #e5e5e5;
}

.board-column-expanded .board-add-icon a { line-height: 50%; }

/* ##################  *         UI  * ################## */
header {
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #8CCA8D), color-stop(1, #4BBF6B));
  background: -moz-linear-gradient(top, #8CCA8D 5%, #4BBF6B 100%);
  background: -webkit-linear-gradient(top, #8CCA8D 5%, #4BBF6B 100%);
  background: -o-linear-gradient(top, #8CCA8D 5%, #4BBF6B 100%);
  background: -ms-linear-gradient(top, #8CCA8D 5%, #4BBF6B 100%);
  background: linear-gradient(to bottom, #8CCA8D 5%, #4BBF6B 100%);
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#8CCA8D', endColorstr='#4BBF6B',GradientType=0);
  background-color: #7892c2;
  padding: 5px;
  margin-left: 0px;
  margin-right: 0px;
  margin-top: 0px;
  margin-bottom: 0px !important;
  border-bottom: none;
}

header h1 {
  font-size: 24px;
  color: white;
  font-weight: 600;
  padding-left: 10px;
}

header h1 a {
  color: white;
  padding-left: 10px;
}

.page-header {
  padding: 0px 0px 5px 15px;
  background-color: #E2E4E6;
  font-size: small;
}

.sidebar-content > .page-header {
  padding: 5px 0px 5px 15px;
  border-radius: 3px;
}

.sidebar > ul li.active { border-left: 2.5px solid #333; }
.sidebar > ul li:hover { border-left: 2.5px solid #555; }

.page-header h2 {
  border-bottom: none;
  color: #4D4D4D;
}
.project-header {
  font-size: 13px;
  margin-bottom: 10px;
  background-color: #fafafa;
  border-bottom: 1px solid #ececec;
  padding: 5px 15px;
}

.page {
  margin-left: 0px !important;
  margin-right: 0px !important;
}

h1 {
  font-weight: normal;
  color: #FFFFFF;
}

body {
  margin-left: 0px;
  margin-right: 0px;
  margin-top: 0px;
  padding-bottom: 0px;
  padding-top: 0px;
  color: #333;
  font-family: "Source Sans Pro", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

.page {
  margin-left: 20px;
  margin-right: 20px;
  clear: both;
}

.ui-sortable { padding: 0px 2px 0px 2px; }
.sidebar > ul a { color: #271e1e; }
.sidebar {
  padding-left: 10px;
  min-width: 100px;
  font-size: small;
}

/* unvisited & visited link */
a:link, a:visited {
  color: rgb(0, 0, 0);
  text-decoration: none;
}

/* mouse over & selected link */
a:hover, a:active {
  color: rgb(128, 128, 128);
  text-decoration: none;
}

div.color-yellow, div.color-blue, div.color-green,
div.color-purple, div.color-red, div.color-orange,
div.color-grey, div.color-brown, div.color-deep_orange,
div.color-dark_grey, div.color-pink, div.color-teal,
div.color-cyan, div.color-lime, div.color-light_green,
div.color-amber {
  border-left-width: 15px;
  background-color: white;
}

div.task-board-recent {
  border-width: 1px !important;
  border-left-width: 4px !important;
  background-color: white !important;
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 1px 2px rgba(186,186,186,0.5);
  border-left-width: 4px !important;
  border-right: none;
  border-top: 1px solid #ececec !important;
  border-bottom: none;
}

.filter-box input[type=text] { max-width: 300px; }

.accordion-section {
  margin-left: 20px;
  margin-right: 20px;
}

.task-board-collapsed { font-size: 14px; }
.task-board { font-size: 15px; }

@media (max-width: 600px) {
  .popover-form .form-column {
    float: none;
    margin-right: 3%;
    max-width: none;
    min-width: inherit;
  }
  
  input.form-input-large { width: 90%; }
}

/* GITLAB LOOKALIKE */
.board-column-header {
  width: initial;
  border-top-left-radius: 2px;
  border-top-right-radius: 2px;
  /*background: #c4c4c4;*/
  background: #fafafa; /*rgba(91, 141, 220, 0.95);*/
  border: 1px solid #e5e5e5;
  border-radius: 2px;
  position: relative;
  margin: 0;
  padding: 12px;
  font-size: 16px;
  border-bottom: 1px solid #e5e5e5;
}

.task-board-age, .task-board-avatars { display: none; }
.task-board-category-container { text-align: left; }
.task-board-title > a { font-family: "Roboto", sans-serif; }

/* HOLDER OF TASKS */
tr.board-swimlane > td {
  background-color: #fafafa;
  border-radius: 13px;
  /* Gitlab */
  -webkit-flex: 1;
  flex: 1;
  height: 400px;
  margin-bottom: 0;
  padding: 5px;
  /*overflow-y: scroll;*/
  overflow-x: hidden;
  background: #fafafa;
  border: 1px solid #e5e5e5;
  border-radius: 0px 0px 10px 10px;
  /* Gitlab end */
}

th.board-swimlane-header {
  background-color: white;
  border-bottom: 0px solid #CCC;
  border-top: 0px solid #CCC;
  border-left: 0px solid #CCC;
  font-size: 14px;
  line-height: 22px;
}

/* THE SINGLE TASKS LAYOUT */
.board-task-list > div {
  font-size: 13px;
  border-left-width: 5px !important;
  background-color: white !important;
  background: #fff;
  border-radius: 3px;
  padding: 6px 4px 6px 6px;
  margin-bottom: 8px;
  margin-left: 8px;
  margin-right: 8px;
  box-shadow:  0 1px 2px rgba(62, 54, 54, 0.55); /*0 1px 2px rgba(186,186,186,0.5);*/
  border-right: none;
  border-top: 1px solid #ececec !important;
  border-bottom: none;
}

/* Duedata, subtasks, relations, etc. */
.task-board-icons { margin-top: 2px; }

/* Hidden priority 'P0,P1,P2,P3'. Not relevant when it's P0. Should be combined with JS for dynamic */
.task-board-priority { display: none; }

/* The task title - go for initial if it should stay on same line */
.task-board-title {
  font-size: 14px;
  display: inline-block;
  margin-bottom: 5px;
}

/* SIZE OF COLUMN WHEN HIDDEN (MINIMIZED) */
#board th.board-column-header-collapsed {
  width: 5px;
  min-width: 5px;
}