Upload Android Library into Gradle with Artifactory

Bintray 를 서비스하는 JFrog 에서 아키펙트 패키지(Gradle 나 maven, docker 등 저장소)를 관리하는 소프트를 제작하는데, 그것이 바로 Artifactory 이다. 그 중 Pro 버전은 유료지만, oss라 하여 오픈 소스 버전 (즉 커뮤니티 버전) 이 있는데, 이 것을 사용해서 자체적인 Gradle 저장소를 만들 수 있다.

이 글에서는 VPS 환경에서 자체적인 Gradle 저장소를 만들고, 배포하는 방법을 작성하려 한다.

주의할 점으로, 이 글에서는 Docker 설치나 환경 설정에 대해 언급하지는 않는다.

서버 환경

Vultr Cloud Compute의 $10 서버, 즉 40GB SSD / 2GB RAM / 2TB Bandwidth / 1 CPU(Skylake CPU) 를 사용헀고, OS 는 Ubuntu 18.04.1 LTS 이다.

추가적으로, Artifactory 를 안정적으로 Serve 하기 위해 Docker, PostgreSQL 를 사용했다.

Docker-compose 준비

Artifactory 도커 이미지에는 standalone 으로 돌아갈 수 있게 하는 프로그램이 들어가 있기 때문에, 아래의 명령어 1줄이면 쉽게 구동할 수 있다.

docker run --name artifactory -d -p 8081:8081 docker.bintray.io/jfrog/artifactory-oss:latest  

다만 이 방법은 여러 설정을 하려면 명령어가 길어지고, 여러 개의 컨테이너를 동시에 사용해야 될 경우 각각 하나마다 동작 상태를 확인해야 하는 문제가 있어 Docker-compose 를 사용하여 임의의 설정 파일을 만들고 설정 파일을 docker 에 올리는 방법을 사용한다.

여기서 Docker-compose 란 여러 개의 컨테이너를 한 데에 묶어 컨테이너를 순차적으로 생성하는 역할을 한다. Artifcatory 를 구동하기 위해서는 Artifactory 컨테이너와 DB 역할이 되는 PostgreSQL 컨테이너가 필요하기 때문에, 일일히 run 으로 돌리기 보다는 Docker-compose 를 이용해 한번에 관리하려 한다.

다행히도, JFrog가 Github 에 Docker-compose 예제 파일을 올려두어 모든 것을 다 작업할 필요는 없지만, 위 서버 환경에서 적용했을 때 문제가 있어 아래에 정리하려 한다.

Artifactory 구동에 필요한 환경 설정

구동에 필요한 환경 설정 작업은 다음과 같다.

  • 데이터 폴더 생성
  • 기본 설정 파일 복사
  • 권한 설정

데이터 폴더 생성

# mkdir -p /data/postgresql
# mkdir -p /data/artifactory/etc
# mkdir -p /data/nginx/conf.d
# mkdir -p /data/nginx/logs
# mkdir -p /data/nginx/ssl

sudo 권한으로 접근해 위 명령어를 실행하면 된다.

기본 설정 파일 복사

기본 설정 파일에 대해서는 Jfrog/artifactory-docker-examples에 전부 포함되어 있다. 기본 설정 파일 자체를 수정할 필요는 없으니 각각 맞는 경로에 복사하면 된다. 기본 설정 파일의 경로는 이쪽이다.

  1. /data/artifactory 폴더에 access 폴더 안 내용을 삽입한다. 즉, /data/artifactory/access/etc/keys 에 private.key, root.crt 가 있어야 한다.
  2. /data/nginx/conf.d/oss 폴더에 artifactory.conf 를 삽입한다.

권한 설정

Artifactory 6.2.0 부터 artifactory 라는 유저를 생성하여 그 유저만 /data/artifactory 폴더를 접근할 수 있게 변경되었다.

# chown -R 1030:1030 /data/artifactory
# chown -R 104:107 /data/nginx

sudo 권한으로 접근해 위 명령어를 실행하면 된다. 여기서 1030, 104 및 107은 미리 정의된 값으로 사용자에 맞게 수정하면 될 것 같다.

Docker-compose 파일 작성

일반적 문법은 여기서 설명하지 않으나, 기본적인 것을 설명하자면 Docker-compose 의 설정 파일은 yml 확장자를 가지고 있으며, 각 depth 에 컨테이너 이름과 그 정보를 넣는다. 자세한 문법은 Docker-compose version 2 reference 문서를 참고하면 된다.

version: '2'
services:
  postgresql:
    image: library/postgres:latest
    container_name: postgresql
    ports:
     - 5432:5432
    environment:
     - POSTGRES_DB=artifactory
     # The following must match the DB_USER and DB_PASSWORD values passed to Artifactory
     - POSTGRES_USER=artifactory
     - POSTGRES_PASSWORD=password
    volumes:
     - /data/postgresql:/var/lib/postgresql/data
    restart: always
    ulimits:
      nproc: 65535
      nofile:
        soft: 32000
        hard: 40000
  artifactory:
    image: docker.bintray.io/jfrog/artifactory-oss:latest
    container_name: artifactory
    ports:
     - 80:8081
    depends_on:
     - postgresql
    links:
     - postgresql
    volumes:
     - /data/artifactory:/var/opt/jfrog/artifactory
    environment:
     - DB_TYPE=postgresql
     # The following must match the POSTGRES_USER and POSTGRES_PASSWORD values passed to PostgreSQL
     - DB_USER=artifactory
     - DB_PASSWORD=password
     # Add extra Java options by uncommenting the following line
     #- EXTRA_JAVA_OPTIONS=-Xmx4g
    restart: always
    ulimits:
      nproc: 65535
      nofile:
        soft: 32000
        hard: 40000

위 코드를 artifcatory-oss-postgres.yml 라는 이름으로 만들어 서버에 올리면 된다.

Docker-compose 실행

환경 설정도 완료되고, yml 파일도 만들었다면 이제 실행만 하면 된다.

sudo docker-compose -f artifactory-oss-postgresql.yml up -d

위 명령어를 실행하면 postgresql 이미지 와 artifactory 이미지를 pulling 하여 자동으로 받아오고, 실행을 시작한다. up 뒤 -d 옵션을 주는 것으로 사용자가 종료하지 않는 이상 이 컨테이너는 백그라운드에서 계속 구동될 것이다.

이제, 브라우저 등으로 http://localhost 에 접속하면 아래와 같은 창이 나올 것이다.

사진에선 나오지 않아 설명하기 어려우나 처음에 들어가면 초기 설정 팝업이 뜨면서 비밀번호 설정 – 프록시 설정 – 사용 저장소 설정 순서로 나오게 되는데, 프록시 설정은 넘겨도 무방하며, 사용 저장소는 ‘Gradle’ 와 ‘Maven’ 을 선택한다.

여기까지 하면 Gradle 저장소에 대한 구축은 모두 된 것이며, 이제 스튜디오로 넘어와 라이브러리를 업로드하면 된다.

라이브러리 업로드

라이브러리를 업로드하는 것은 다소 어렵지 않게 구성이 가능하다. 업로드 플러그인을 추가하고, 정보를 기재해 명령어를 실행하는 것 뿐이다.

업로드 플러그인 추가

루트 프로젝트의 build.gradle 에 아래 classpath 를 추가한다.

//Check for the latest version here: http://plugins.gradle.org/plugin/com.jfrog.artifactory
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"

라이브러리 프로젝트의 build.gradle 에 플러그인을 적용한다.

apply plugin: "com.jfrog.artifactory"
apply plugin: 'maven-publish'

프로젝트 정보 기재

플러그인을 정의한 곳 밑에 변수를 추가한다.

def groupId = "com.github.windsekirun"
def version = "1.0.0"
def artifectId = "AwesomeLibraryForDebug"

def Properties properties = new Properties()
properties.load(project.rootProject.file("local.properties").newDataInputStream())

groupId, version, artifectId 는 각각 그룹, 버전, 아키펙트 이름을 나타낸다. gradle 의존성 문구의 규칙 또한 그룹:아키펙트 이름:버전 이므로 위 정보를 가지고 올리면 com.github.windsekirun:AwesomeLibraryForDebug:1.0.0 이 된다.

그 다음 줄의 Properties 의 경우에 저장소에 올리기 위해 아이디 / 비밀번호를 적어야 하는데, 개인 정보가 코드에 올라가야 되지 않게 해야 하므로 local.properties 에서 불러오도록 코드를 추가하였다. 이와 관련된 자세한 사항은 Insert resValue in gradle file 글에서 볼 수 있다.

플러그인 설정

위에서 프로젝트마다 별도로 설정해야 하는 정보는 모두 기재했으므로, 아래부터는 공통 정보이다.

publishing {
    publications {
        aar(MavenPublication) {
            groupId packageName
            version = libraryVersion
            artifactId projectName

            // Tell maven to prepare the generated "*.aar" file for publishing
            artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
        }
    }
}

artifactory {
    contextUrl = 'ARTIFACTORY URL'
    publish {
        repository {
            // The Artifactory repository key to publish to
            repoKey = 'libs-release-local'

            // personal information will locate at local.properties
            username = properties.getProperty("artifactory.username", "")
            password = properties.getProperty("artifactory.password", "")
        }
        defaults {
            // Tell the Artifactory Plugin which artifacts should be published to Artifactory.
            publications('aar')
            publishArtifacts = true

            // Publish generated POM files to Artifactory (true by default)
            publishPom = true
        }
    }
}

위 코드를 dependencies 문단 밑 (즉 맨 하단)에 넣어주면 된다.

명령어 실행

./gradlew assembleRelease artifactoryPublish

모든 작업이 완료되면, 위 커맨드를 터미널에 실행함으로서 Gradle 저장소에 올라가게 된다.

올라간 정보는 Artifactory 페이지 내 Artifacts 부분에서 찾아볼 수 있다.

위 사진과 같이 aar 와 pom 파일이 같이 올라가고, aar 파일을 클릭했을 때 Dependency Declaration 부분에 정상적으로 나오면 성공이다.

다른 프로젝트에서 불러오기

다른 프로젝트에서 불러오기 위해서는, 모듈의 build.gradle 에 아래 코드를 삽입하면 된다.

repositories {
    maven { url "ARTIFACTORY_URL/list/libs-release-local/" }
}

dependencies {
    implementation "com.github.windsekirun:AwesomeLibraryForDebug:1.0.0"
}

참고로 여기서 예제로 들은 AwesomeLibraryForDebug 는 존재하지 않으므로 시도하지 않아도 된다.

OPCache :: Increase WordPress, NextCloud Performance

워드프레스나 NextCloud는 PHP 기반으로 돌아가게 되는데, NextCloud 12 Server Tuning 글에 보면 Enable PHP OpCache 란 섹션이 있다.

나머지 http2, MariaDB 사용 까지는 ‘제로부터 시작하는 NextCloud 설치하기‘  에 있고,  Redis-based Transactional File Locking 도 적용되어 있다. (나중에 기회되면 설명하려고 한다.)

그래서 남은 항목인 OPCache 에 대해 정리하려고 한다.

OPCache란?

OPcache는 PHP script 를 bytecode로 컴파일한 후에 공유 메모리에 저장하여 성능을 향상시키는 모듈이다.
5.5 이상부터 PHP에 내장되어 있는데, 설정 방법은 php.ini 파일을 열어서 아래 구문들을 추가해주면 된다.

경로는 /etc/php/7.0/fpm/php.ini이다.

opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1

각각 구문에 대한 설명은 아래와 같다.

  • enable : OPCache 활성화 여부
  • enable_cli : CLI 버전의 PHP에서 OPCache 활성화 여부
  • interned_strings_buffer : 내부 문자열을 저장할 때 사용되는 메모리 양(MB), PHP 5.3.0 이상만 적용됨
  • max_accelerated_files : OPCache 해시 테이블의 최대 키 수 (= 스크립트 수)를 적는다. 사용되는 실제 값은 리스트 (223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987) 에서 설정한 값과 같거나 큰 수 중 첫번째 숫자가 된다. 최소는 200이고, 최대는 PHP 5.5.6 미만에서는 100,000 이고, 그 이상은 1.000.000 이다.
  • memory_consumption : OPCache 가 사용하는 공유 메모리 저장 영역의 크기 (MB)
  • save_comments: false면 모든 주석이 opcache 캐시에서 삭제되어 Doctrine, Zend Framework 2 와 같은 주석 구문에 의존하는 기능이 작동하지 않음
  • revalidate_freq: 타임스탬프 기준에서 어느 시간을 기점으로 업데이트 할건지 결정함

적용 후 서비스 재적용을 해준다.

sudo systemctl restart php7.0-fpm.service

 

제로부터 시작하는 NextCloud 설치하기 on VPS

NextCloudDropbox 와 비슷하게 파일 호스팅 서비스를 제공하는 솔루션인데, 개인 서버에도 설치할 수 있다.

오늘 퇴근하고 나서 약 5시간 동안 삽질 끝에 설치에 성공했는데, 겸사겸사 정리도 해보려고 한다.

환경

OS는 Ubuntu 16.04 LTS 를 사용할 것이며, 아래 조건을 만족해야 한다. (예제에서는 16.10을 사용한다.)

  1. SSH 접속 가능한 상태
  2. 터미널에 두려움을 가지지 않는 용기
  3. 설명이 없어도 알아서 구글링하는 용기

목적

제목대로, 제로부터 NextCloud 구축까지 시행할 것이다.

즉, 아무것도 없는 상태에서 Nginx, PHP-FPM, MariaDB, Let’s Encrypt SSL 연결, NextCloud 까지 전부 설정을 마칠 것이다.

작업 예상시간은 1시간 이하이다.

참고로, [ ] 로 감싸진 것의 경우 자기가 원하는 정보로 교체하면 된다.

0. VPS 구매하기

VPS 는 웹호스팅과 서버호스팅의 중간 형태로, 하나의 물리 서버를 여러 개의 가상 서버로 나누어 사용하면서 각각의 가상 서버를 독립적으로 운영할 수 있게 하는 것이다.

여기서는 Vultr 에 있는 UzukiLive 서버에서 진행한다. 옵션은 아래와 같다.

NextCloud를 어느정도까지 사용할 것에 따라 다르지만, 보통 2 CPU 에 16GB 이상이 150명까지 환경에 적당하다고 한다.

Deployment Recommendation 에 어느정도 나와있으니 자기의 목적에 맞는 VPS 를 찾아보자.

나는 적어도 혼자나 많아봤자 5~6명일거라서, 기존에 $5 옵션 이었던 1 CPU 1GB 에서 1 CPU 2GB 로 증설했다.

1. 루트 유저 추가하기

초기 서버 설정으로 관리용 계정을 root 이외에 하나 더 만드는 것이다.

마음에 드는 터미널로 접속하자.

ssh root@***.***.***.***

비밀번호는 Vultr 기준 인스턴스 메인에 있다.

adduser [pyxis]

유저를 추가하는 명령어이다.

그러면 비밀번호와 정보를 물어볼텐데, 적당히 채워주고 생성을 마친다.

usermod -aG sudo [pyxis]

그리고 방금 추가한 유저에게 root 권한을 부여한다.

이렇게 해서 루트 유저 추가가 끝났고, 만든 유저로 로그인하자.

ssh pyxis@***.***.***.***

이런 메세지가 표시되면 성공한 것이다.

2. Nginx

Nginx Web Server 로, Apache 를 쓸 수도 있었지만 개인적으로는 Nginx 가 좀 더 친숙했으므로 Nginx 를 사용하려고 한다.

sudo apt-get -y install nginx

위 명령어로 Nginx 를 설치한다.

한 가지 팁으로, sudo 를 일일히 치기 귀찮다면 sudo -i로 root 모드로 들어간 상태에서 진행할 수 있다.

설치를 다 한다음, sudo nano /etc/nginx/nginx.conf를 입력해서 에디터를 연다.

user www-data;
worker_processes 8;
pid /run/nginx.pid;
 
events {
    worker_connections 768;
    # multi_accept on;                                                                                                                                                                                                                   
}
 
http {
 
    ##                                                                                                                                                                                                                                   
    # Basic Settings                                                                                                                                                                                                                     
    ##                                                                                                                                                                                                                                   
 
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;                                                                                                                                                                                                                 
 
    # server_names_hash_bucket_size 64;                                                                                                                                                                                                  
    # server_name_in_redirect off;                                                                                                                                                                                                       
 
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

worker_processes 값과 server_tokens 값을 변경하는데, 각각 설명은 다음과 같다.

  • worker_processes: 하나의 worker 가 동시에 실행할 수 있는 Thread 수이다.
  • server_tokens: 서버 버전 정보 표시 금지

참고로 nano 의 사용법을 몰라도 이 세개만 기억하면 된다.

  • 방향키: 이동, 백스페이스: 지우기
  • control + K : 라인 지우기
  • control + X : 저장

변경한 후, Nginx 의 서비스를 재시작해주자.

sudo systemctl restart nginx.service

3. NextCloud 다운로드

현재 최신버전은 12.0.3 이다.

cd /var/www
sudo wget https://download.nextcloud.com/server/releases/nextcloud-12.0.3.zip
unzip nextcloud-12.0.3.zip
rm -rf nextcloud-12.0.3.zip

이런 구조로 되면 된다.

4. NextCloud 폴더에 권한 설정

sudo adduser nextcloud
sudo chown -R nextcloud:www-data /var/www/nextcloud
sudo chmod -R o-rwx /var/www/nextcloud

nextcloud 유저를 만든 다음, 해당 유저 및 www-data 그룹을 방금 압축을 푼 /var/www/nextcloud 에 권한을 설정한다.

5. PHP-FPM 설정

5.6 에 비해 7.0에서 좀 더 php의 속도가 증가했으므로 7.0을 설치하기를 추천한다.

sudo apt-get -y install php-cli php-json php-curl php-imap php-gd php-mysql php-xml php-zip php-intl php-mcrypt php-imagick php-mbstring
sudo apt-get install -y php-fpm

설치가 다 되면 /etc/php/7.0/fpm/pool.d 폴더에 nextcloud 전용 설정 파일을 만든다.

[nextcloud]
listen = /var/run/nextcloud.sock
 
listen.owner = nextcloud
listen.group = www-data
 
user = nextcloud
group = www-data
 
pm = ondemand
pm.max_children = 30
pm.process_idle_timeout = 60s
pm.max_requests = 500
 
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

다 만들었으면 php 서비스를 재시작하자.

sudo systemctl restart php7.0-fpm.service

6. MariaDB 설치

sudo apt-get install -y mariadb-server mariadb-client

MySQL 를 사용해도 상관없다.

$ sudo mysql_secure_installation
 
Set root password? [Y/n] Y
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

7. Nextcloud 데이터베이스 설정

sudo mysql -u root -p
MariaDB> CREATE DATABASE nextcloud;
Query OK, 1 row affected (0.00 sec)

MariaDB> CREATE USER "nextcloud"@"localhost";
Query OK, 0 rows affected (0.00 sec)
 
MariaDB> SET password FOR "nextcloud"@"localhost" = password('[PASSWORD]');
Query OK, 0 rows affected (0.00 sec)
 
MariaDB> GRANT ALL PRIVILEGES ON nextcloud.* TO "nextcloud"@"localhost" IDENTIFIED BY "[PASSWORD]";
Query OK, 0 rows affected (0.00 sec)
 
MariaDB> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB> EXIT
Bye

PASSWORD 는 마지막 NextCloud 설정할 때 필요하니 잘 기억해두자.

8. Nginx 설정 파일 만들기

사실 하나하나 추가해야 되지만, 여기서는 완전한 파일만 기재한다.

/etc/nginx/sites-available 폴더에 nextcloud 란 이름으로 파일을 만든다.

upstream php-handler {

    server unix:/var/run/nextcloud.sock;
}

server {

    listen 80;
    listen [::]:80;
    server_name [cloud.uzuki.live];

    root /var/www/nextcloud/;

    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';

    location = /robots.txt {

        allow all;
        log_not_found off;
        access_log off;
    }

    location = /.well-known/carddav {

        return 301 $scheme://$host/remote.php/dav;
    }

    location = /.well-known/caldav {

        return 301 $scheme://$host/remote.php/dav;
    }

    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    location / {

        rewrite ^ /index.php$uri;
    }

    location ~ ^/.well-known/acme-challenge/* {

        allow all;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {

        deny all;
    }

    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {

        deny all;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {

        try_files $uri/ =404;
        index index.php;
    }

    location ~* \.(?:css|js|woff|svg|gif)$ {

        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=7200";
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;

        access_log off;
    }

    location ~* \.(?:png|html|ttf|ico|jpg|jpeg)$ {

        try_files $uri /index.php$uri$is_args$args;
        access_log off;
    }
}
sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/nextcloud
nginx -t

심볼릭 링크를 생성하고 설정 파일이 문법에 맞는지 확인한다.

이와 같이 나온다면 재시작을 해주자.

sudo systemctl restart nginx.service
sudo systemctl restart php7.0-fpm.service

9. Let’s Encrypt로 SSL 인증받기

이 작업을 위해서는 도메인이 필요하다. NextCloud 는 SSL 이하 사용을 권장하므로 Self-Signing 라도 해야되지만 SSL 인증서를 구매하거나 적어도 Let’s Encrypt 로 인증을 거쳐야 한다.

sudo apt-get install -y software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install -y certbot
sudo certbot certonly --webroot -w /var/www/nextcloud --agree-tos --email [pyxis@uzuki.live] -d [cloud.uzuki.live] --rsa-key-size 4096

인증이 완료되었다고 나오면 dhparams 키도 추가로 생성해주자.

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
sudo chmod 600 /etc/ssl/certs/dhparam.pem

참고로 꽤나 오래 걸리므로 커피 한잔 마시고 오는 것이 좋다.

10. SSL 설정 반영하기

/etc/nginx/sites-available/nextcloud 를 수정한다.

Let’s Encrypt 로 받은 pem 키와 위에서 생성한 dhparam 키를 각각 넣어준다.

upstream php-handler {

    server unix:/var/run/nextcloud.sock;
}

server {

    listen 80;
    listen [::]:80;
    server_name [cloud.uzuki.live];
    return 301 https://$server_name$request_uri;
}

server {

    listen 443 ssl;
    listen [::]:443 ssl;
    server_name [cloud.uzuki.live];

    root /var/www/nextcloud/;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/[cloud.uzuki.live]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[cloud.uzuki.live]/privkey.pem;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 1440m;
    ssl_buffer_size 8k;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED';
    ssl_prefer_server_ciphers on;

    ssl_trusted_certificate /etc/letsencrypt/live/cloud.uzuki.live/chain.pem;
    ssl_stapling on;
    ssl_stapling_verify on;

    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';

    location = /robots.txt {

        allow all;
        log_not_found off;
        access_log off;
    }

    location = /.well-known/carddav {

        return 301 $scheme://$host/remote.php/dav;
    }

    location = /.well-known/caldav {

        return 301 $scheme://$host/remote.php/dav;
    }

    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    location / {

        rewrite ^ /index.php$uri;
    }

    location ~ ^/.well-known/acme-challenge/* {

        allow all;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {

        deny all;
    }

    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {

        deny all;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {

        try_files $uri/ =404;
        index index.php;
    }

    location ~* \.(?:css|js|woff|svg|gif)$ {

        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=7200";
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        # Optional: Don't log access to assets
        access_log off;
    }

    location ~* \.(?:png|html|ttf|ico|jpg|jpeg)$ {

        try_files $uri /index.php$uri$is_args$args;
        access_log off;
    }
}
sudo systemctl reload nginx.service

위 설정들은 SSL Test를 A+ 로 통과할 수 있는 설정이나 필요한 조건에 따라 더 추가할 수 있다.

11. 인증서 자동 갱신

Let’s Encrypt 는 무료인 대신 90일 마다 갱신을 해줘야 한다. crontab 로 자동으로 갱신하도록 설정해준다.

crontab -e
42 23 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log

12. http2

기존 http 1.1 을 개선한 http의 새로운 프로토콜로, 여러 방법을 사용하여 지연 시간을 감소시킨 프로토콜이다.

위 11번의 설정 파일에서 16 ~ 17줄 부분에 교체만 해주면 된다.

listen 443 ssl http2;
listen [::]:443 ssl http2;

13. 타임아웃 설정

1. /etc/php/7.0/fpm/pool.d/nextcloud.conf 맨 밑 request_terminate_timeout = 300 추가

2. /etc/nginx/sites-available/nextcloud 의 105번째 줄 밑에 fastcgi_read_timeout 300; 추가

14. 접속

마지막으로 server_name 로 설정한 주소로 들어가보면 설정 마법사가 나온다.

이미지 출처: https://www.pcextreme.nl/community/d/153-set-up-your-own-cloud-storage-within-minutes-using-nextcloud-and-aurora-s3

맨 위 두개 필드에는 아이디와 비번을, 그 다음에는 파일을 보관할 장소를 적는다.

마지막 4개 필드에는 7번에서 설정한 데이터베이스 정보를 넣는데, 각각 유저 이름, 비밀번호, 데이터베이스 이름, 주소를 넣는다.

만일 finish setup 에서 넘어가지 않다면 맨 밑 localhost 를 localhost:3306 으로 변경하면 되는 것 같다.

15. 끝

총 15단계에 걸쳐서 설치가 끝났다.

추가적으로 OPCache, redis 를 설치하면 더 속도가 상승되지만 그건 나중에 언급해도 괜찮을 것 같다.