├── .github └── CODEOWNERS ├── LICENSE ├── README.md ├── logs └── cron_example ├── lookerapp_ansible ├── README.md ├── defaults │ └── main.yml ├── files │ ├── jmxremote.access │ └── jmxremote.password ├── handlers │ └── main.yaml ├── tasks │ ├── cron.yml │ ├── javaversion.yml │ ├── limits.yml │ ├── main.yaml │ ├── ntp.yml │ └── phantomjs.yml └── templates │ ├── looker.j2 │ └── looker_init.j2 ├── reverse_proxy_examples └── apache_looker_vhost.conf ├── ssh_tunnels └── tunnel.sample └── startup_scripts ├── README.md ├── looker ├── looker11 ├── looker_init ├── looker_mac ├── lookerstart.cfg ├── monitrc └── systemd ├── README.md └── looker.service /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @looker-open-source/cloud-looker-devrel 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Looker Data Sciences, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | customer-scripts 2 | 3 | Publicly available scripts for on-premise hosted Looker customers. These scripts are examples of best-practices for Looker automation tasks. They are provided as-is, and may need modification to work in your environment. See the [public documentation](https://docs.looker.com/setup-and-management/on-prem-install/looker-startup-options) for startup options. 4 | 5 | * startup_scripts: init, monit and process startup scripts for looker 6 | * lookerapp_ansible: Ansible role to install the Looker client 7 | * inotify_scripts: model files synchronization for clustered Lookers 8 | * logs: examples for managing Looker log files 9 | -------------------------------------------------------------------------------- /logs/cron_example: -------------------------------------------------------------------------------- 1 | # Examples for zipping and then deleting old Looker logs. 2 | # Please customize for your environment. 3 | # 4 | # zip logs 5 | 9 1 * * * find $HOME/looker/log -name 'looker.log.????????' -mtime +7 -exec gzip '{}' \; > /dev/null 6 | # delete logs 7 | 29 1 * * * find $HOME/looker/log -name 'looker.log.????????.gz' -mtime +28 -exec rm -f '{}' \; > /dev/null 8 | -------------------------------------------------------------------------------- /lookerapp_ansible/README.md: -------------------------------------------------------------------------------- 1 | Ansible role to install Looker 2 | 3 | This role will likely only work on Ubuntu 12+ 4 | 5 | Prerequisites: 6 | 7 | * Oracle Java 1.8 8 | * A looker user with home dir of /home/looker 9 | * [jq](https://stedolan.github.io/jq/) 10 | * Jar download example from our [docs](https://docs.looker.com/setup-and-management/on-prem-install/download-looker-jar#calling_the_api). 11 | 12 | Vars you need to set: 13 | 14 | Valid email 15 | , Valid license 16 | , Looker Release 17 | -------------------------------------------------------------------------------- /lookerapp_ansible/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Variables here are applicable to looker app deployment 3 | 4 | # looker account name 5 | lookerops: looker 6 | lookeropsgr: looker 7 | s3_url: GET_FROM_LOOKER 8 | deploy_jar: looker-latest.jar 9 | deploy_oss_jar: looker-dependencies-latest.jar 10 | deploy_dir: /home/looker/looker 11 | jmx_security_dir: /home/looker/.lookerjmx 12 | port: 9999 13 | 14 | javamem: { "m1.small": "1200m", "m1.medium": "2300m", "m1.large": "4800m", "m3.medium": "2300m", "m3.large": "4800m"} 15 | 16 | phantomjs_version: 2.1.1 17 | phantomjs_url: https://bitbucket.org/ariya/phantomjs/downloads 18 | 19 | -------------------------------------------------------------------------------- /lookerapp_ansible/files/jmxremote.access: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Default Access Control File for Remote JMX(TM) Monitoring 3 | ###################################################################### 4 | # 5 | # Access control file for Remote JMX API access to monitoring. 6 | # This file defines the allowed access for different roles. The 7 | # password file (jmxremote.password by default) defines the roles and their 8 | # passwords. To be functional, a role must have an entry in 9 | # both the password and the access files. 10 | # 11 | # The default location of this file is $JRE/lib/management/jmxremote.access 12 | # You can specify an alternate location by specifying a property in 13 | # the management config file $JRE/lib/management/management.properties 14 | # (See that file for details) 15 | # 16 | # The file format for password and access files is syntactically the same 17 | # as the Properties file format. The syntax is described in the Javadoc 18 | # for java.util.Properties.load. 19 | # A typical access file has multiple lines, where each line is blank, 20 | # a comment (like this one), or an access control entry. 21 | # 22 | # An access control entry consists of a role name, and an 23 | # associated access level. The role name is any string that does not 24 | # itself contain spaces or tabs. It corresponds to an entry in the 25 | # password file (jmxremote.password). The access level is one of the 26 | # following: 27 | # "readonly" grants access to read attributes of MBeans. 28 | # For monitoring, this means that a remote client in this 29 | # role can read measurements but cannot perform any action 30 | # that changes the environment of the running program. 31 | # "readwrite" grants access to read and write attributes of MBeans, 32 | # to invoke operations on them, and optionally 33 | # to create or remove them. This access should be granted 34 | # only to trusted clients, since they can potentially 35 | # interfere with the smooth operation of a running program. 36 | # 37 | # The "readwrite" access level can optionally be followed by the "create" and/or 38 | # "unregister" keywords. The "unregister" keyword grants access to unregister 39 | # (delete) MBeans. The "create" keyword grants access to create MBeans of a 40 | # particular class or of any class matching a particular pattern. Access 41 | # should only be granted to create MBeans of known and trusted classes. 42 | # 43 | # For example, the following entry would grant readwrite access 44 | # to "controlRole", as well as access to create MBeans of the class 45 | # javax.management.monitor.CounterMonitor and to unregister any MBean: 46 | # controlRole readwrite \ 47 | # create javax.management.monitor.CounterMonitorMBean \ 48 | # unregister 49 | # or equivalently: 50 | # controlRole readwrite unregister create javax.management.monitor.CounterMBean 51 | # 52 | # The following entry would grant readwrite access as well as access to create 53 | # MBeans of any class in the packages javax.management.monitor and 54 | # javax.management.timer: 55 | # controlRole readwrite \ 56 | # create javax.management.monitor.*,javax.management.timer.* \ 57 | # unregister 58 | # 59 | # The \ character is defined in the Properties file syntax to allow continuation 60 | # lines as shown here. A * in a class pattern matches a sequence of characters 61 | # other than dot (.), so javax.management.monitor.* matches 62 | # javax.management.monitor.CounterMonitor but not 63 | # javax.management.monitor.foo.Bar. 64 | # 65 | # A given role should have at most one entry in this file. If a role 66 | # has no entry, it has no access. 67 | # If multiple entries are found for the same role name, then the last 68 | # access entry is used. 69 | # 70 | # 71 | # Default access control entries: 72 | # o The "monitorRole" role has readonly access. 73 | # o The "controlRole" role has readwrite access and can create the standard 74 | # Timer and Monitor MBeans defined by the JMX API. 75 | 76 | monitorRole readonly 77 | controlRole readwrite \ 78 | create javax.management.monitor.*,javax.management.timer.* \ 79 | unregister 80 | -------------------------------------------------------------------------------- /lookerapp_ansible/files/jmxremote.password: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------- 2 | # Template for jmxremote.password 3 | # 4 | # o Copy this template to jmxremote.password 5 | # o Set the user/password entries in jmxremote.password 6 | # o Change the permission of jmxremote.password to read-only 7 | # by the owner. 8 | # 9 | # See below for the location of jmxremote.password file. 10 | # ---------------------------------------------------------------------- 11 | 12 | ############################################################## 13 | # Password File for Remote JMX Monitoring 14 | ############################################################## 15 | # 16 | # Password file for Remote JMX API access to monitoring. This 17 | # file defines the different roles and their passwords. The access 18 | # control file (jmxremote.access by default) defines the allowed 19 | # access for each role. To be functional, a role must have an entry 20 | # in both the password and the access files. 21 | # 22 | # Default location of this file is $JRE/lib/management/jmxremote.password 23 | # You can specify an alternate location by specifying a property in 24 | # the management config file $JRE/lib/management/management.properties 25 | # or by specifying a system property (See that file for details). 26 | 27 | 28 | ############################################################## 29 | # File permissions of the jmxremote.password file 30 | ############################################################## 31 | # Since there are cleartext passwords stored in this file, 32 | # this file must be readable by ONLY the owner, 33 | # otherwise the program will exit with an error. 34 | # 35 | # The file format for password and access files is syntactically the same 36 | # as the Properties file format. The syntax is described in the Javadoc 37 | # for java.util.Properties.load. 38 | # Typical password file has multiple lines, where each line is blank, 39 | # a comment (like this one), or a password entry. 40 | # 41 | # 42 | # A password entry consists of a role name and an associated 43 | # password. The role name is any string that does not itself contain 44 | # spaces or tabs. The password is again any string that does not 45 | # contain spaces or tabs. Note that passwords appear in the clear in 46 | # this file, so it is a good idea not to use valuable passwords. 47 | # 48 | # A given role should have at most one entry in this file. If a role 49 | # has no entry, it has no access. 50 | # If multiple entries are found for the same role name, then the last one 51 | # is used. 52 | # 53 | # In a typical installation, this file can be read by anybody on the 54 | # local machine, and possibly by people on other machines. 55 | # For # security, you should either restrict the access to this file, 56 | # or specify another, less accessible file in the management config file 57 | # as described above. 58 | # 59 | # Following are two commented-out entries. The "measureRole" role has 60 | # password "QED". The "controlRole" role has password "R&D". 61 | # 62 | monitorRole MYMONITORROLEPASS 63 | controlRole MYCONTROLROLEPASS 64 | 65 | -------------------------------------------------------------------------------- /lookerapp_ansible/handlers/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: looker_restart 4 | service: name=looker state=restarted 5 | -------------------------------------------------------------------------------- /lookerapp_ansible/tasks/cron.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - cron: user="{{ lookerops }}" name="zip logs" minute="9" hour="1" job="find $HOME/looker/log -name 'looker.log.????????' -mtime +7 -exec gzip '{}' \; > /dev/null" 4 | - cron: user="{{ lookerops }}" name="delete logs" minute="29" hour="1" job="find $HOME/looker/log -name 'looker.log.????????.gz' -mtime +28 -exec rm -f '{}' \; > /dev/null" 5 | -------------------------------------------------------------------------------- /lookerapp_ansible/tasks/javaversion.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: get version from java 4 | command: java -version 5 | register: javaout 6 | changed_when: false 7 | 8 | - set_fact: jvout="{{ javaout.stderr }}" 9 | 10 | - set_fact: 11 | java_version="java7" 12 | - set_fact: 13 | java_version="java6" 14 | when: jvout | match('.*java version\s+"1\.6\.*') 15 | - set_fact: 16 | java_version="java7" 17 | when: jvout | match('.*java version\s+"1\.7\.*') 18 | - set_fact: 19 | java_version="java8" 20 | when: jvout | match('.*java version\s+"1\.8\.*') 21 | 22 | -------------------------------------------------------------------------------- /lookerapp_ansible/tasks/limits.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - lineinfile: dest=/etc/security/limits.conf state=present line="{{ lookerops }} soft core unlimited" 4 | - lineinfile: dest=/etc/security/limits.conf state=present line="{{ lookerops }} hard core unlimited" 5 | - lineinfile: dest=/etc/security/limits.conf state=present line="{{ lookerops }} soft nofile 4096" 6 | - lineinfile: dest=/etc/security/limits.conf state=present line="{{ lookerops }} hard nofile 4096" 7 | 8 | 9 | -------------------------------------------------------------------------------- /lookerapp_ansible/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: ntp.yml 4 | - include: limits.yml 5 | - include: javaversion.yml 6 | - include: phantomjs.yml 7 | 8 | - set_fact: 9 | email: 10 | license: 11 | latest: 12 | 13 | - name: Set up looker/.lookerjmx directory 14 | file: state=directory path={{ jmx_security_dir }} mode=0700 owner={{ lookerops }} group={{ lookeropsgr }} 15 | 16 | - name: Set up looker/looker directory 17 | file: state=directory path={{ deploy_dir }} mode=0750 owner={{ lookerops }} group={{ lookeropsgr }} 18 | 19 | - name: Copy validated jar download url 20 | shell: | 21 | wget -q -O- --post-data="{\"lic\": \"{{ license }}\", \"email\": \"{{ email }}\", \"latest\":\"{{ latest }}\"}" --header=Content-Type:application/json "https://apidownload.looker.com/download" > ~/response.txt 22 | 23 | - name: Parse response and download jar 24 | shell: | 25 | wget -O "looker-latest.jar" "$(cat ~/response.txt | jq .url -r)" 26 | 27 | - name: Parse response and download dependency jar 28 | shell: | 29 | wget -O "looker-dependencies-latest.jar" "$(cat ~/response.txt | jq .url -r)" 30 | 31 | - name: Copy jmx security files to looker home 32 | copy: src={{ item }} dest={{ jmx_security_dir }}/{{ item }} owner={{ lookerops }} group={{ lookeropsgr }} mode=0400 33 | with_items: 34 | - jmxremote.access 35 | - jmxremote.password 36 | 37 | - name: Copy looker startup files 38 | template: src=looker_init.j2 dest=/etc/init.d/looker mode=0755 owner=root group=root 39 | 40 | - template: src=looker.j2 dest={{ deploy_dir }}/looker mode=0750 owner={{ lookerops }} group={{ lookeropsgr }} 41 | 42 | - name: Start Looker 43 | service: name=looker state=started enabled=yes 44 | 45 | - include: cron.yml 46 | 47 | - meta: flush_handlers 48 | -------------------------------------------------------------------------------- /lookerapp_ansible/tasks/ntp.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Common tasks playbook 3 | 4 | - name: Ensure NTP is installed 5 | apt: pkg=ntp force=yes state=present 6 | when: ansible_os_family == "Debian" 7 | 8 | - yum: name=ntp state=present 9 | when: ansible_os_family == "RedHat" 10 | 11 | - name: Ensure NTPD is running 12 | service: name=ntp state=running 13 | when: ansible_os_family == "Debian" 14 | 15 | - service: name=ntpd state=running 16 | when: ansible_os_family == "RedHat" 17 | 18 | -------------------------------------------------------------------------------- /lookerapp_ansible/tasks/phantomjs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install prerequisites 4 | apt: name=fontconfig state=latest update_cache=yes force=yes 5 | 6 | - name: Copy phantomjs install file to root home 7 | get_url: url={{ phantomjs_url }}/phantomjs-{{ phantomjs_version }}-linux-{{ ansible_machine }}.tar.bz2 dest=/root/phantomjs-{{ phantomjs_version }}-linux-{{ ansible_machine }}.tar.bz2 mode=0640 owner=root group=root 8 | 9 | - name: unpack 10 | command: tar -xjf /root/phantomjs-{{ phantomjs_version }}-linux-{{ ansible_machine }}.tar.bz2 chdir=/usr/local/share creates=/usr/local/share/phantomjs-{{ phantomjs_version }}-linux-{{ ansible_machine }} 11 | 12 | - name: link phantomjs dir 13 | file: path=/usr/local/share/phantomjs src=/usr/local/share/phantomjs-{{ phantomjs_version }}-linux-{{ ansible_machine }} owner=root group=root state=link 14 | 15 | - name: link phantomjs commands 16 | file: path=/usr/local/bin/{{ item }} src=/usr/local/share/phantomjs/bin/{{ item }} owner=root group=root state=link 17 | with_items: 18 | - phantomjs 19 | 20 | 21 | -------------------------------------------------------------------------------- /lookerapp_ansible/templates/looker.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd $HOME/looker 4 | # set your java memory- there should be over 1.5G of system memory 5 | # left to run the OS 6 | MEM=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'` 7 | JM=`expr $MEM \* 6 / 10` 8 | JAVAMEM="${JM}k" 9 | 10 | 11 | # Extra Java startup args and Looker startup args. These can also be set in 12 | # a file named lookerstart.cfg 13 | JMXARGS="-Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.port=9910 -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.ssl=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.local.only=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.authenticate=true -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.access.file=${HOME}/.lookerjmx/jmxremote.access -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.password.file=${HOME}/.lookerjmx/jmxremote.password" 14 | 15 | # to set up JMX monitoring, add JMXARGS to JAVAARGS 16 | JAVAARGS="" 17 | LOOKERARGS="--force-gcm-encryption" 18 | 19 | # check for a lookerstart.cfg file to set JAVAARGS and LOOKERARGS 20 | if [ -r ./lookerstart.cfg ]; then 21 | . ./lookerstart.cfg 22 | fi 23 | 24 | LOOKERPORT=${LOOKERPORT:-"9999"} 25 | 26 | start() { 27 | if [ -e .deploying ]; then 28 | echo "Startup suppressed: ${PWD}/.deploying file exists. Remove .deploying file to allow startup" 29 | exit 1 30 | fi 31 | 32 | LOCKFILE=.starting 33 | if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then 34 | echo "Startup suppressed: ${LOCKFILE} contains running pid, startup script is already running" 35 | exit 1 36 | fi 37 | 38 | # make sure the lockfile is removed when we exit and then claim it 39 | trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT 40 | echo $$ > ${LOCKFILE} 41 | 42 | fixcrypt 43 | java \ 44 | -XX:+UseG1GC -XX:MaxGCPauseMillis=2000 \ 45 | -Xms$JAVAMEM -Xmx$JAVAMEM \ 46 | -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps \ 47 | -Xloggc:/tmp/gc.log ${JAVAARGS} \ 48 | -jar looker.jar start ${LOOKERARGS} 49 | 50 | if [ -x ./tunnel ]; then 51 | ./tunnel start 52 | fi 53 | 54 | rm -f ${LOCKFILE} 55 | } 56 | 57 | stop() { 58 | pid=`cat .tmp/looker.pid` 59 | if [ -f .status_server_token ] && [ -x /usr/bin/curl ]; then 60 | state="running" 61 | token=`cat .status_server_token` 62 | request="control/stop?token=${token}" 63 | timeout 20 curl -m 10 -ks https://127.0.0.1:${LOOKERPORT}/${request} > /dev/null 2>&1 64 | ECODE=$? 65 | [ $ECODE -eq 7 ] && state="stopped" 66 | if [ $ECODE -gt 7 ] ; then 67 | kill $pid 68 | fi 69 | for i in {1..30}; do 70 | timeout 20 curl -m 5 -ks https://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 71 | ECODE=$? 72 | if [ $ECODE -eq 7 ]; then 73 | state="stopped" 74 | break 75 | fi 76 | if [ $ECODE -gt 7 ] ; then 77 | kill -9 $pid 78 | fi 79 | sleep 1 80 | done 81 | if [ "${state}" = "running" ]; then 82 | echo "Force Stop Looker Web Application" 83 | kill $pid 84 | kill -0 $pid && kill -9 $pid 85 | fi 86 | else 87 | timeout 20 java -jar looker.jar stop 88 | if [ $? -ne 0 ]; then 89 | kill -9 $pid 90 | fi 91 | fi 92 | } 93 | 94 | fixcrypt() { 95 | CRYPTEXIST=`/sbin/ldconfig -p | grep -c '\slibcrypt.so\s'` 96 | 97 | if [ $CRYPTEXIST -eq 0 ]; then 98 | if [ ! -d .tmp ]; then 99 | mkdir .tmp 100 | fi 101 | CRYPTLN=`/sbin/ldconfig -p | grep '\slibcrypt\.so\.[[:digit:]]' | awk '{print $(NF)}'` 102 | ln -s -f $CRYPTLN `pwd`/.tmp/libcrypt.so 103 | export LD_LIBRARY_PATH=`pwd`/.tmp/:$LD_LIBRARY_PATH 104 | fi 105 | } 106 | 107 | case "$1" in 108 | start) 109 | start 110 | ;; 111 | stop) 112 | stop 113 | ;; 114 | restart) 115 | echo "Restarting Looker Web Application" "looker" 116 | stop 117 | sleep 3 118 | start 119 | ;; 120 | status) 121 | curl -ks https://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 122 | if [ $? -eq 7 ]; then 123 | echo "Status:Looker Web Application stopped" 124 | exit 7 125 | else 126 | echo "Status:Looker Web Application running" 127 | exit 0 128 | fi 129 | ;; 130 | *) 131 | java -jar looker.jar $1 132 | ;; 133 | esac 134 | 135 | exit 0 136 | -------------------------------------------------------------------------------- /lookerapp_ansible/templates/looker_init.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: looker 4 | # Required-Start: $remote_fs $all 5 | # Required-Stop: 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 8 | # Short-Description: Looker Web Application 9 | ### END INIT INFO 10 | 11 | # /etc/init.d/looker: start and stop the Looker Web application 12 | 13 | test -x {{ deploy_dir }}/looker || exit 0 14 | 15 | umask 022 16 | 17 | # Set some defaults 18 | LOOKERDIR={{ deploy_dir }} 19 | LOOKERUSER=looker 20 | 21 | USER=`whoami` 22 | 23 | if test -f /etc/default/looker; then 24 | . /etc/default/looker 25 | fi 26 | 27 | . /lib/lsb/init-functions 28 | 29 | pidfile=${LOOKERDIR}/.tmp/looker.pid 30 | 31 | if [ -r ${pidfile} ]; then 32 | looker_pid=`cat ${pidfile}` 33 | fi 34 | 35 | if [ "$USER" != "${LOOKERUSER}" ]; then 36 | if [ "$USER" = "root" ]; then 37 | exec su -l ${LOOKERUSER} -c "$0 $@" 38 | fi 39 | echo "Script must be run from ${LOOKERUSER} or root. You are '${USER}'" 40 | exit 1 41 | fi 42 | 43 | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" 44 | 45 | cd ${LOOKERDIR} 46 | 47 | start() { 48 | log_daemon_msg "Starting Looker Web Application" "looker" || true 49 | ./looker start 50 | } 51 | 52 | stop() { 53 | log_daemon_msg "Stopping Looker Web Application" "looker" || true 54 | ./looker stop 55 | } 56 | 57 | case "$1" in 58 | start) 59 | start 60 | ;; 61 | stop) 62 | stop 63 | ;; 64 | 65 | restart) 66 | log_daemon_msg "Restarting Looker Web Application" "looker" || true 67 | ./looker restart 68 | ;; 69 | 70 | status) 71 | ./looker status 72 | exit $? 73 | ;; 74 | 75 | *) 76 | log_action_msg "Usage: /etc/init.d/looker {start|stop|restart|status}" || true 77 | exit 1 78 | esac 79 | 80 | exit 0 81 | 82 | -------------------------------------------------------------------------------- /reverse_proxy_examples/apache_looker_vhost.conf: -------------------------------------------------------------------------------- 1 | # This configuration was tested with Apache 2.4.7. 2 | # 3 | # Apache will need the following modules enabled in order to load this configuration: 4 | # authz_core.load 5 | # headers 6 | # mime 7 | # mpm_prefork 8 | # proxy 9 | # proxy_http 10 | # rewrite 11 | # setenvif 12 | # socache_shmcb 13 | # ssl 14 | # headers 15 | 16 | 17 | ServerName HOSTNAME.DOMAIN.COM 18 | ErrorLog logs/looker_ssl_error_log 19 | CustomLog logs/looker_ssl_access_log combined 20 | LogLevel warn 21 | # Set headers and configuration appropriately for Looker 22 | RequestHeader add X-Forwarded-Proto https 23 | RequestHeader add Accept-Encoding "" 24 | ProxyIOBufferSize 131072 25 | ProxyReceiveBufferSize 32768 26 | # The URL of the Looker host (use https if the Looker host is running SSL) 27 | ProxyPass / http://LOOKERHOST.DOMAIN.COM:9999/ connectiontimeout=65 timeout=3600 28 | ProxyPassreverse / http://LOOKERHOST.DOMAIN.COM:9999/ 29 | # Uncomment the SSLProxy directives if the Looker host is running SSL 30 | #SSLProxyEngine on 31 | #SSLProxyVerify none 32 | #SSLProxyCheckPeerCN off 33 | #SSLProxyCheckPeerName off 34 | #SSLProxyCheckPeerExpire off 35 | SSLEngine on 36 | # Either real certificates or self-signed certs should be referenced here 37 | SSLCertificateFile /path/to/ssl/certificate/file 38 | SSLCACertificateFile /path/to/ssl/ca/certificate/file 39 | SSLCertificateKeyFile /path/to/ssl/certificate/key/file 40 | # Rewrite incoming URLs 41 | RewriteEngine on 42 | RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) 43 | RewriteRule .* - [F] 44 | RewriteCond %{HTTP_HOST} "!^HOSTNAME.DOMAIN.COM" 45 | RewriteRule ^(.*)$ https://HOSTNAME.DOMAIN.COM/$1 [R=permanent,L,NE] 46 | 47 | 48 | -------------------------------------------------------------------------------- /ssh_tunnels/tunnel.sample: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Template for tunnel startup 3 | # Set the user, key, server and port forward, then copy to ~/looker/tunnel, 4 | # set to mode 750 5 | # 6 | # When using more than one autossh config, eg for more than one ssh server endpoint 7 | # these startup scripts can be named tunnel_1, tunnel_2, etc. Adjust the pidfile to 8 | # avoid collisions by naming them autossh[12].pid A wrapper around all of the tunnel 9 | # startups can be created passing $1 to each for the start|stop arg 10 | # 11 | # For multiple db endpoints reachable from the same tunnel server, it's convenient 12 | # to simply add an additional -L :: 13 | # 14 | # More than one -i can be supplied during key-rotation operations to ensure 15 | # uptime 16 | # 17 | # 18 | 19 | cd $HOME/looker 20 | export AUTOSSH_PIDFILE=$HOME/looker/.autossh.pid 21 | unset SSH_AUTH_SOCK 22 | 23 | start() { 24 | autossh -M0 -f -N -T \ 25 | -L 1234:mydb:1234 \ 26 | -i myuserkey -o TCPKeepAlive=yes \ 27 | -o ServerAliveInterval=30 \ 28 | looker@tunnelserver 29 | } 30 | 31 | pidtest() { 32 | if [ -e $AUTOSSH_PIDFILE ]; then 33 | PSLINE=`ps --no-headers -p $( cat $AUTOSSH_PIDFILE ) | grep autossh` 34 | if [ -z "$PSLINE" ]; then 35 | retval=1 36 | else 37 | retval=0 38 | fi 39 | else 40 | retval=3 41 | fi 42 | return "$retval" 43 | } 44 | 45 | case $1 in 46 | start) 47 | # Checked the PID file exists and check the actual status of process 48 | pidtest 49 | status=$? 50 | # If the status is SUCCESS then don't need to start again. 51 | if [ $status = "0" ]; then 52 | echo "Tunnel already running" 53 | exit 0 54 | fi 55 | # Start the daemon. 56 | echo "Starting Tunnel" 57 | start 58 | ;; 59 | stop) 60 | # Stop the daemon. 61 | pidtest 62 | status=$? 63 | if [ "$status" = 0 ]; then 64 | kill $( cat $AUTOSSH_PIDFILE ) 65 | else 66 | echo "Tunnel is not running" 67 | fi 68 | ;; 69 | restart) 70 | # Restart the daemon. 71 | $0 stop && sleep 2 && $0 start 72 | ;; 73 | status) 74 | # Check the status of the process. 75 | pidtest 76 | status=$? 77 | if [ "$status" = 0 ]; then 78 | echo "Tunnel is running" 79 | exit 0 80 | else 81 | echo "Tunnel is not running" 82 | exit $status 83 | fi 84 | ;; 85 | reload) 86 | # Reload the process. Basically sending some signal to a daemon to reload 87 | # it configurations. 88 | if [ -e $AUTOSSH_PIDFILE ]; then 89 | kill -usr1 $( cat $AUTOSSH_PIDFILE ) 90 | fi 91 | ;; 92 | *) 93 | # For invalid arguments, print the usage message. 94 | echo "Usage: $0 {start|stop|restart|reload|status}" 95 | exit 2 96 | ;; 97 | esac 98 | -------------------------------------------------------------------------------- /startup_scripts/README.md: -------------------------------------------------------------------------------- 1 | # Startup Scripts 2 | 3 | Publicly available scripts for on-premise hosted Looker customer startup. See the [public documentation](https://docs.looker.com/setup-and-management/on-prem-install/looker-startup-options) for startup options. 4 | 5 | * looker: Startup script for looker running under Java 1.8. Should be in the /home/looker/looker directory with the looker.jar file, and it should be named looker. The full path to the file will commonly be /home/looker/looker/looker. Use this script for all current versions of Looker. 6 | * looker11: Startup script for looker running with OpenJDK11. Should be in the /home/looker/looker directory with the looker.jar file, and it *should be named looker*. The full path to the file will commonly be /home/looker/looker/looker. Several things depend on this script being renamed from looker11->looker, so make sure to do this. 7 | * looker_init: Ubuntu init file to start Looker automatically on boot. This may need some customization depending on user/directory for Looker. This will also need to be modified to work with RedHat-based Linux distributions. 8 | * looker_mac: A version of the startup script customized for OSX. May require customization. 9 | * monitrc: Very basic sample monitrc to manage the Looker process. 10 | 11 | 12 | ### To set Looker to start on boot for an Ubuntu host: 13 | 14 | #### 16.04 LTS and later 15 | 16.04 LTS and later use `systemd` to manage services. Please follow the instructions in [systemd](systemd). 16 | 17 | #### For versions before 16.04 LTS 18 | * Download a copy of looker_init to your Looker server. 19 | * As root, save looker_init to /etc/init.d/looker 20 | * As root, edit /etc/init.d/looker. Near the top of the script, change the values of LOOKERDIR and LOOKERUSER if you are using a non-default location or user. 21 | * As root run ```chmod a+x /etc/init.d/looker``` 22 | * As root run ```update-rc.d looker defaults``` 23 | 24 | -------------------------------------------------------------------------------- /startup_scripts/looker: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd $HOME/looker 4 | # set your java memory- there should be over 1.5G of system memory 5 | # left to run the OS 6 | MEM=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'` 7 | JM=`expr $MEM \* 6 / 10` 8 | JAVAMEM="${JM}k" 9 | METAMEM="800m" 10 | 11 | # Extra Java startup args and Looker startup args. These can also be set in 12 | # a file named lookerstart.cfg 13 | JMXARGS="-Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.port=9910 -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.ssl=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.local.only=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.authenticate=true -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.access.file=${HOME}/.lookerjmx/jmxremote.access -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.password.file=${HOME}/.lookerjmx/jmxremote.password" 14 | 15 | # to set up JMX monitoring, add JMXARGS to JAVAARGS 16 | JAVAARGS="" 17 | LOOKERARGS="--force-gcm-encryption" 18 | 19 | # check for a lookerstart.cfg file to set JAVAARGS and LOOKERARGS 20 | if [ -r ./lookerstart.cfg ]; then 21 | . ./lookerstart.cfg 22 | fi 23 | 24 | # check if --no-ssl is specified in LOOKERARGS and set protocol accordingly 25 | PROTOCOL="" 26 | 27 | echo "${LOOKERARGS}" | grep -q "\-\-no\-ssl" 28 | if [ $? -eq 0 ] 29 | then 30 | PROTOCOL='http' 31 | else 32 | PROTOCOL='https' 33 | fi 34 | LOOKERPORT=${LOOKERPORT:-"9999"} 35 | 36 | start() { 37 | if [ -e .deploying ]; then 38 | echo "Startup suppressed: ${PWD}/.deploying file exists. Remove .deploying file to allow startup" 39 | exit 1 40 | fi 41 | 42 | LOCKFILE=.starting 43 | if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then 44 | echo "Startup suppressed: ${LOCKFILE} contains running pid, startup script is already running" 45 | exit 1 46 | fi 47 | 48 | # make sure the lockfile is removed when we exit and then claim it 49 | trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT 50 | echo $$ > ${LOCKFILE} 51 | 52 | fixcrypt 53 | java \ 54 | -XX:+UseG1GC -XX:MaxGCPauseMillis=2000 -XX:MaxMetaspaceSize=$METAMEM \ 55 | -Xms$JAVAMEM -Xmx$JAVAMEM \ 56 | -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps \ 57 | -Xloggc:/tmp/gc.log ${JAVAARGS} \ 58 | -jar looker.jar start ${LOOKERARGS} 59 | 60 | if [ -x ./tunnel ]; then 61 | ./tunnel start 62 | fi 63 | 64 | rm -f ${LOCKFILE} 65 | } 66 | 67 | stop() { 68 | pid=`cat .tmp/looker.pid` 69 | if [ -f .status_server_token ] && [ -x /usr/bin/curl ]; then 70 | state="running" 71 | token=`cat .status_server_token` 72 | request="control/stop?token=${token}" 73 | timeout 20 curl -m 10 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/${request} > /dev/null 2>&1 74 | ECODE=$? 75 | [ $ECODE -eq 7 ] && state="stopped" 76 | if [ $ECODE -gt 7 ] ; then 77 | kill $pid 78 | fi 79 | for i in {1..30}; do 80 | timeout 20 curl -m 5 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 81 | ECODE=$? 82 | if [ $ECODE -eq 7 ]; then 83 | state="stopped" 84 | break 85 | fi 86 | if [ $ECODE -gt 7 ] ; then 87 | kill -9 $pid 88 | fi 89 | sleep 1 90 | done 91 | if [ "${state}" = "running" ]; then 92 | echo "Force Stop Looker Web Application" 93 | kill $pid 94 | kill -0 $pid && kill -9 $pid 95 | fi 96 | else 97 | timeout 20 java -jar looker.jar stop 98 | if [ $? -ne 0 ]; then 99 | kill -9 $pid 100 | fi 101 | fi 102 | } 103 | 104 | fixcrypt() { 105 | CRYPTEXIST=`/sbin/ldconfig -p | grep -c '\slibcrypt.so\s'` 106 | 107 | if [ $CRYPTEXIST -eq 0 ]; then 108 | if [ ! -d .tmp ]; then 109 | mkdir .tmp 110 | fi 111 | CRYPTLN=`/sbin/ldconfig -p | grep '\slibcrypt\.so\.[[:digit:]]' | awk '{print $(NF)}'` 112 | ln -s -f $CRYPTLN `pwd`/.tmp/libcrypt.so 113 | export LD_LIBRARY_PATH=`pwd`/.tmp/:$LD_LIBRARY_PATH 114 | fi 115 | } 116 | 117 | case "$1" in 118 | start) 119 | start 120 | ;; 121 | stop) 122 | stop 123 | ;; 124 | restart) 125 | echo "Restarting Looker Web Application" "looker" 126 | stop 127 | sleep 3 128 | start 129 | ;; 130 | status) 131 | curl -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 132 | if [ $? -eq 7 ]; then 133 | echo "Status:Looker Web Application stopped" 134 | exit 7 135 | else 136 | echo "Status:Looker Web Application running" 137 | exit 0 138 | fi 139 | ;; 140 | *) 141 | java -jar looker.jar $* 142 | ;; 143 | esac 144 | 145 | exit 0 146 | -------------------------------------------------------------------------------- /startup_scripts/looker11: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # This is the startup script for Looker using OpenJDK11. Looker supports 5 | # OpenJDK11 starting with the 7.16 release 6 | # 7 | 8 | JAVA_VER=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1) 9 | if [ "$JAVA_VER" -ne 11 ]; then 10 | WHERE=`which java` 11 | echo "This script runs with OpenJDK11, your executable $WHERE has Java major version $JAVA_VER" 12 | exit 1 13 | fi 14 | 15 | cd $HOME/looker 16 | # set your java memory- there should be over 1.5G of system memory 17 | # left to run the OS 18 | MEM=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'` 19 | JM=`expr $MEM \* 6 / 10` 20 | JAVAMEM="${JM}k" 21 | METAMEM="800m" 22 | 23 | # Extra Java startup args and Looker startup args. These can also be set in 24 | # a file named lookerstart.cfg 25 | JMXARGS="-Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.port=9910 -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.ssl=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.local.only=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.authenticate=true -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.access.file=${HOME}/.lookerjmx/jmxremote.access -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.password.file=${HOME}/.lookerjmx/jmxremote.password" 26 | 27 | # Starting with JDK9 some reflective accesses log warning messages, these java 28 | # args increase module visibility and so suppress the output 29 | REFLECTIVE_ACCESS_ARGS="--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED" 30 | 31 | # Disable optimistic typing in Nashorn (the JDK Javascript interpreter). 32 | # This flag defaults to True in JDK 11 (previously False in JDK 8) and in this 33 | # configuration it causes large spikes in Metaspace use in some circumstances. 34 | export NASHORN_ARGS="-Dnashorn.args=--optimistic-types=false" 35 | 36 | # to set up JMX monitoring, add JMXARGS to JAVAARGS 37 | JAVAARGS="" 38 | LOOKERARGS="--force-gcm-encryption" 39 | 40 | # check for a lookerstart.cfg file to set JAVAARGS and LOOKERARGS 41 | if [ -r ./lookerstart.cfg ]; then 42 | . ./lookerstart.cfg 43 | fi 44 | 45 | # check if --no-ssl is specified in LOOKERARGS and set protocol accordingly 46 | PROTOCOL="" 47 | 48 | echo "${LOOKERARGS}" | grep -q "\-\-no\-ssl" 49 | if [ $? -eq 0 ] 50 | then 51 | PROTOCOL='http' 52 | else 53 | PROTOCOL='https' 54 | fi 55 | LOOKERPORT=${LOOKERPORT:-"9999"} 56 | 57 | start() { 58 | if [ -e .deploying ]; then 59 | echo "Startup suppressed: ${PWD}/.deploying file exists. Remove .deploying file to allow startup" 60 | exit 1 61 | fi 62 | 63 | LOCKFILE=.starting 64 | if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then 65 | echo "Startup suppressed: ${LOCKFILE} contains running pid, startup script is already running" 66 | exit 1 67 | fi 68 | 69 | # make sure the lockfile is removed when we exit and then claim it 70 | trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT 71 | echo $$ > ${LOCKFILE} 72 | 73 | fixcrypt 74 | java \ 75 | -XX:+UseG1GC -XX:MaxGCPauseMillis=2000 -XX:MaxMetaspaceSize=$METAMEM \ 76 | -Xms$JAVAMEM -Xmx$JAVAMEM \ 77 | -Xlog:gc*,gc+ref=debug,gc+heap=debug,gc+age=debug:file=/tmp/gc-%p-%t.log:tags,uptime,time,level:filecount=7,filesize=10m \ 78 | ${REFLECTIVE_ACCESS_ARGS} \ 79 | ${NASHORN_ARGS} \ 80 | ${JAVAARGS} \ 81 | -jar looker.jar start ${LOOKERARGS} 82 | 83 | if [ -x ./tunnel ]; then 84 | ./tunnel start 85 | fi 86 | 87 | rm -f ${LOCKFILE} 88 | } 89 | 90 | stop() { 91 | pid=`cat .tmp/looker.pid` 92 | if [ -f .status_server_token ] && [ -x /usr/bin/curl ]; then 93 | state="running" 94 | token=`cat .status_server_token` 95 | request="control/stop?token=${token}" 96 | timeout 20 curl -m 10 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/${request} > /dev/null 2>&1 97 | ECODE=$? 98 | [ $ECODE -eq 7 ] && state="stopped" 99 | if [ $ECODE -gt 7 ] ; then 100 | kill $pid 101 | fi 102 | for i in {1..30}; do 103 | timeout 20 curl -m 5 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 104 | ECODE=$? 105 | if [ $ECODE -eq 7 ]; then 106 | state="stopped" 107 | break 108 | fi 109 | if [ $ECODE -gt 7 ] ; then 110 | kill -9 $pid 111 | fi 112 | sleep 1 113 | done 114 | if [ "${state}" = "running" ]; then 115 | echo "Force Stop Looker Web Application" 116 | kill $pid 117 | kill -0 $pid && kill -9 $pid 118 | fi 119 | else 120 | timeout 20 java -jar looker.jar stop 121 | if [ $? -ne 0 ]; then 122 | kill -9 $pid 123 | fi 124 | fi 125 | } 126 | 127 | fixcrypt() { 128 | CRYPTEXIST=`/sbin/ldconfig -p | grep -c '\slibcrypt.so\s'` 129 | 130 | if [ $CRYPTEXIST -eq 0 ]; then 131 | if [ ! -d .tmp ]; then 132 | mkdir .tmp 133 | fi 134 | CRYPTLN=`/sbin/ldconfig -p | grep '\slibcrypt\.so\.[[:digit:]]' | awk '{print $(NF)}'` 135 | ln -s -f $CRYPTLN `pwd`/.tmp/libcrypt.so 136 | export LD_LIBRARY_PATH=`pwd`/.tmp/:$LD_LIBRARY_PATH 137 | fi 138 | } 139 | 140 | case "$1" in 141 | start) 142 | start 143 | ;; 144 | stop) 145 | stop 146 | ;; 147 | restart) 148 | echo "Restarting Looker Web Application" "looker" 149 | stop 150 | sleep 3 151 | start 152 | ;; 153 | status) 154 | curl -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 155 | if [ $? -eq 7 ]; then 156 | echo "Status:Looker Web Application stopped" 157 | exit 7 158 | else 159 | echo "Status:Looker Web Application running" 160 | exit 0 161 | fi 162 | ;; 163 | *) 164 | java -jar looker.jar $* 165 | ;; 166 | esac 167 | 168 | exit 0 169 | -------------------------------------------------------------------------------- /startup_scripts/looker_init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: looker 4 | # Required-Start: $remote_fs $all 5 | # Required-Stop: 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 8 | # Short-Description: Looker Web Application 9 | ### END INIT INFO 10 | 11 | # /etc/init.d/looker: start and stop the Looker Web application 12 | 13 | 14 | # Set some defaults 15 | LOOKERDIR=/home/looker/looker 16 | LOOKERUSER=looker 17 | 18 | if [ ! -x ${LOOKERDIR} ]; then 19 | echo "Looker directory ${LOOKERDIR} does not exist or is not marked exectable." 20 | exit 0 21 | fi 22 | 23 | if [ ! -x ${LOOKERDIR}/looker ]; then 24 | echo "Looker startup script ${LOOKERDIR}/looker does not exist or is not marked exectable." 25 | exit 0 26 | fi 27 | 28 | umask 022 29 | 30 | USER=`whoami` 31 | 32 | if [ -f /etc/default/looker ]; then 33 | . /etc/default/looker 34 | fi 35 | 36 | . /lib/lsb/init-functions 37 | 38 | pidfile=${LOOKERDIR}/.tmp/looker.pid 39 | 40 | if [ -r ${pidfile} ]; then 41 | looker_pid=`cat ${pidfile}` 42 | fi 43 | 44 | if [ "$USER" != "${LOOKERUSER}" ]; then 45 | if [ "$USER" = "root" ]; then 46 | exec su -l ${LOOKERUSER} -c "$0 $@" 47 | fi 48 | echo "Script must be run from ${LOOKERUSER} or root. You are '${USER}'" 49 | exit 1 50 | fi 51 | 52 | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" 53 | 54 | cd ${LOOKERDIR} 55 | 56 | start() { 57 | log_daemon_msg "Starting Looker Web Application" "looker" || true 58 | ./looker start 59 | } 60 | 61 | stop() { 62 | log_daemon_msg "Stopping Looker Web Application" "looker" || true 63 | ./looker stop 64 | } 65 | 66 | case "$1" in 67 | start) 68 | start 69 | ;; 70 | stop) 71 | stop 72 | ;; 73 | 74 | restart) 75 | log_daemon_msg "Restarting Looker Web Application" "looker" || true 76 | ./looker restart 77 | ;; 78 | 79 | status) 80 | ./looker status 81 | exit $? 82 | ;; 83 | 84 | *) 85 | log_action_msg "Usage: /etc/init.d/looker {start|stop|restart|status}" || true 86 | exit 1 87 | esac 88 | 89 | exit 0 90 | 91 | -------------------------------------------------------------------------------- /startup_scripts/looker_mac: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | HOSTTYPE=`uname -s` 4 | 5 | cd $HOME/looker 6 | # set your java memory- there should be over 1.5G of system memory 7 | # left to run the OS 8 | case $HOSTTYPE in 9 | Darwin) 10 | MEM=`hostinfo | grep "Primary memory available" | awk '{print $4}' | awk -F '\.' '{print $1}'` 11 | MEM=`expr $MEM \* 1024 \* 1024` 12 | ;; 13 | Linux) 14 | MEM=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'` 15 | ;; 16 | *) 17 | echo "Unknown host type: ${HOSTTYPE}" 18 | exit 1; 19 | ;; 20 | esac 21 | JM=`expr $MEM \* 6 / 10` 22 | JAVAMEM="${JM}k" 23 | METAMEM="800m" 24 | 25 | # Extra Java startup args and Looker startup args. These can also be set in 26 | # a file named lookerstart.cfg 27 | JMXARGS="-Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.port=9910 -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.ssl=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.local.only=false -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.authenticate=true -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.access.file=${HOME}/.lookerjmx/jmxremote.access -Dcom.sun.akuma.jvmarg.com.sun.management.jmxremote.password.file=${HOME}/.lookerjmx/jmxremote.password" 28 | 29 | # to set up JMX monitoring, add JMXARGS to JAVAARGS 30 | JAVAARGS="" 31 | LOOKERARGS="--force-gcm-encryption" 32 | 33 | # check for a lookerstart.cfg file to set JAVAARGS and LOOKERARGS 34 | if [ -r ./lookerstart.cfg ]; then 35 | . ./lookerstart.cfg 36 | fi 37 | 38 | # check if --no-ssl is specified in LOOKERARGS and set protocol accordingly 39 | PROTOCOL="" 40 | LOOKERPORT=${LOOKERPORT:-"9999"} 41 | 42 | echo "${LOOKERARGS}" | grep -q "\-\-no\-ssl" 43 | if [ $? -eq 0 ] 44 | then 45 | PROTOCOL='http' 46 | else 47 | PROTOCOL='https' 48 | fi 49 | 50 | start() { 51 | if [ -e .deploying ]; then 52 | echo "Startup suppressed: ${PWD}/.deploying file exists. Remove .deploying file to allow startup" 53 | exit 1 54 | fi 55 | 56 | LOCKFILE=.starting 57 | if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then 58 | echo "Startup suppressed: ${LOCKFILE} contains running pid, startup script is already running" 59 | exit 1 60 | fi 61 | 62 | # make sure the lockfile is removed when we exit and then claim it 63 | trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT 64 | echo $$ > ${LOCKFILE} 65 | 66 | case $HOSTTYPE in 67 | Darwin) 68 | ;; 69 | Linux) 70 | fixcrypt 71 | ;; 72 | *) 73 | echo "Unknown host type: ${HOSTTYPE}" 74 | exit 1; 75 | ;; 76 | esac 77 | java \ 78 | -XX:+UseG1GC -XX:MaxGCPauseMillis=2000 -XX:MaxMetaspaceSize=$METAMEM \ 79 | -Xms$JAVAMEM -Xmx$JAVAMEM \ 80 | -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps \ 81 | -Xloggc:/tmp/gc.log ${JAVAARGS} \ 82 | -jar looker.jar start ${LOOKERARGS} 83 | 84 | if [ -x ./tunnel ]; then 85 | ./tunnel start 86 | fi 87 | 88 | rm -f ${LOCKFILE} 89 | } 90 | 91 | stop() { 92 | pid=`cat .tmp/looker.pid` 93 | if [ -f .status_server_token ] && [ -x /usr/bin/curl ]; then 94 | state="running" 95 | token=`cat .status_server_token` 96 | request="control/stop?token=${token}" 97 | case $HOSTTYPE in 98 | Darwin) 99 | curl -m 10 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/${request} > /dev/null 2>&1 100 | ;; 101 | Linux) 102 | timeout 20 curl -m 10 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/${request} > /dev/null 2>&1 103 | ;; 104 | *) 105 | echo "Unknown host type: ${HOSTTYPE}" 106 | exit 1; 107 | ;; 108 | esac 109 | ECODE=$? 110 | [ $ECODE -eq 7 ] && state="stopped" 111 | if [ $ECODE -gt 7 ] ; then 112 | kill $pid 113 | fi 114 | for i in {1..30}; do 115 | case $HOSTTYPE in 116 | Darwin) 117 | curl -m 5 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 118 | ;; 119 | Linux) 120 | timeout 20 curl -m 5 -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 121 | ;; 122 | *) 123 | echo "Unknown host type: ${HOSTTYPE}" 124 | exit 1; 125 | ;; 126 | esac 127 | ECODE=$? 128 | if [ $ECODE -eq 7 ]; then 129 | state="stopped" 130 | break 131 | fi 132 | if [ $ECODE -gt 7 ] ; then 133 | kill -9 $pid 134 | fi 135 | sleep 1 136 | done 137 | if [ "${state}" = "running" ]; then 138 | echo "Force Stop Looker Web Application" 139 | kill $pid 140 | kill -0 $pid && kill -9 $pid 141 | fi 142 | else 143 | case $HOSTTYPE in 144 | Darwin) 145 | java -jar looker.jar stop 146 | ;; 147 | Linux) 148 | timeout 20 java -jar looker.jar stop 149 | ;; 150 | *) 151 | echo "Unknown host type: ${HOSTTYPE}" 152 | exit 1; 153 | ;; 154 | esac 155 | if [ $? -ne 0 ]; then 156 | kill -9 $pid 157 | fi 158 | fi 159 | } 160 | 161 | fixcrypt() { 162 | CRYPTEXIST=`/sbin/ldconfig -p | grep -c '\slibcrypt.so\s'` 163 | 164 | if [ $CRYPTEXIST -eq 0 ]; then 165 | if [ ! -d .tmp ]; then 166 | mkdir .tmp 167 | fi 168 | CRYPTLN=`/sbin/ldconfig -p | grep '\slibcrypt\.so\.[[:digit:]]' | awk '{print $(NF)}'` 169 | ln -s -f $CRYPTLN `pwd`/.tmp/libcrypt.so 170 | export LD_LIBRARY_PATH=`pwd`/.tmp/:$LD_LIBRARY_PATH 171 | fi 172 | } 173 | 174 | case "$1" in 175 | start) 176 | start 177 | ;; 178 | stop) 179 | stop 180 | ;; 181 | restart) 182 | echo "Restarting Looker Web Application" "looker" 183 | stop 184 | sleep 3 185 | start 186 | ;; 187 | status) 188 | curl -ks ${PROTOCOL}://127.0.0.1:${LOOKERPORT}/alive > /dev/null 2>&1 189 | if [ $? -eq 7 ]; then 190 | echo "Status:Looker Web Application stopped" 191 | exit 7 192 | else 193 | echo "Status:Looker Web Application running" 194 | exit 0 195 | fi 196 | ;; 197 | *) 198 | java -jar looker.jar $* 199 | ;; 200 | esac 201 | 202 | exit 0 203 | -------------------------------------------------------------------------------- /startup_scripts/lookerstart.cfg: -------------------------------------------------------------------------------- 1 | # when using a different port, define it here so that the startup 2 | # scripts will point to the right port and add 3 | # --port=${LOOKERPORT} 4 | # to LOOKERARGS 5 | 6 | LOOKERPORT="9999" 7 | JAVAARGS="${JAVAARGS} " 8 | LOOKERARGS="${LOOKERARGS} --port=${LOOKERPORT} --force-gcm-encryption" 9 | -------------------------------------------------------------------------------- /startup_scripts/monitrc: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ## Monit control file 3 | ############################################################################### 4 | ## 5 | ## Comments begin with a '#' and extend through the end of the line. Keywords 6 | ## are case insensitive. All path's MUST BE FULLY QUALIFIED, starting with '/'. 7 | ## 8 | ## Below you will find examples of some frequently used statements. For 9 | ## information about the control file and a complete list of statements and 10 | ## options, please have a look in the Monit manual. 11 | ## 12 | ## 13 | ############################################################################### 14 | ## Global section 15 | ############################################################################### 16 | ## 17 | ## Start Monit in the background (run as a daemon): 18 | # 19 | set daemon 30 # check services at 2-minute intervals 20 | # with start delay 240 # optional: delay the first check by 4-minutes (by 21 | # # default Monit check immediately after Monit start) 22 | # 23 | # 24 | ## Set syslog logging with the 'daemon' facility. If the FACILITY option is 25 | ## omitted, Monit will use 'user' facility by default. If you want to log to 26 | ## a standalone log file instead, specify the full path to the log file 27 | # 28 | # set logfile syslog facility log_daemon 29 | set logfile /var/log/monit.log 30 | # 31 | # 32 | ## Set the location of the Monit id file which stores the unique id for the 33 | ## Monit instance. The id is generated and stored on first Monit start. By 34 | ## default the file is placed in $HOME/.monit.id. 35 | # 36 | # set idfile /var/.monit.id 37 | set idfile /var/lib/monit/id 38 | # 39 | ## Set the location of the Monit state file which saves monitoring states 40 | ## on each cycle. By default the file is placed in $HOME/.monit.state. If 41 | ## the state file is stored on a persistent filesystem, Monit will recover 42 | ## the monitoring state across reboots. If it is on temporary filesystem, the 43 | ## state will be lost on reboot which may be convenient in some situations. 44 | # 45 | set statefile /var/lib/monit/state 46 | # 47 | ## Set the list of mail servers for alert delivery. Multiple servers may be 48 | ## specified using a comma separator. If the first mail server fails, Monit 49 | # will use the second mail server in the list and so on. By default Monit uses 50 | # port 25 - it is possible to override this with the PORT option. 51 | # 52 | # set mailserver mail.bar.baz, # primary mailserver 53 | # backup.bar.baz port 10025, # backup mailserver on port 10025 54 | # localhost # fallback relay 55 | # 56 | # 57 | ## By default Monit will drop alert events if no mail servers are available. 58 | ## If you want to keep the alerts for later delivery retry, you can use the 59 | ## EVENTQUEUE statement. The base directory where undelivered alerts will be 60 | ## stored is specified by the BASEDIR option. You can limit the maximal queue 61 | ## size using the SLOTS option (if omitted, the queue is limited by space 62 | ## available in the back end filesystem). 63 | # 64 | set eventqueue 65 | basedir /var/lib/monit/events # set the base directory where events will be stored 66 | slots 100 # optionally limit the queue size 67 | # 68 | # 69 | ## Send status and events to M/Monit (for more informations about M/Monit 70 | ## see http://mmonit.com/). By default Monit registers credentials with 71 | ## M/Monit so M/Monit can smoothly communicate back to Monit and you don't 72 | ## have to register Monit credentials manually in M/Monit. It is possible to 73 | ## disable credential registration using the commented out option below. 74 | ## Though, if safety is a concern we recommend instead using https when 75 | ## communicating with M/Monit and send credentials encrypted. 76 | # 77 | # set mmonit http://monit:monit@192.168.1.10:8080/collector 78 | # # and register without credentials # Don't register credentials 79 | # 80 | # 81 | ## Monit by default uses the following format for alerts if the the mail-format 82 | ## statement is missing:: 83 | ## --8<-- 84 | ## set mail-format { 85 | ## from: monit@$HOST 86 | ## subject: monit alert -- $EVENT $SERVICE 87 | ## message: $EVENT Service $SERVICE 88 | ## Date: $DATE 89 | ## Action: $ACTION 90 | ## Host: $HOST 91 | ## Description: $DESCRIPTION 92 | ## 93 | ## Your faithful employee, 94 | ## Monit 95 | ## } 96 | ## --8<-- 97 | ## 98 | ## You can override this message format or parts of it, such as subject 99 | ## or sender using the MAIL-FORMAT statement. Macros such as $DATE, etc. 100 | ## are expanded at runtime. For example, to override the sender, use: 101 | # 102 | # set mail-format { from: monit@foo.bar } 103 | # 104 | # 105 | ## You can set alert recipients whom will receive alerts if/when a 106 | ## service defined in this file has errors. Alerts may be restricted on 107 | ## events by using a filter as in the second example below. 108 | # 109 | # set alert sysadm@foo.bar # receive all alerts 110 | ## Do not alert when Monit start,stop or perform a user initiated action 111 | # set alert manager@foo.bar not on { instance, action } 112 | # 113 | # 114 | ## Monit has an embedded web server which can be used to view status of 115 | ## services monitored and manage services from a web interface. See the 116 | ## Monit Wiki if you want to enable SSL for the web server. 117 | # 118 | set httpd port 2812 and 119 | use address localhost # only accept connection from localhost 120 | allow localhost # allow localhost to connect to the server and 121 | # allow admin:monit # require user 'admin' with password 'monit' 122 | # allow @monit # allow users of group 'monit' to connect (rw) 123 | # allow @users readonly # allow users of group 'users' to connect readonly 124 | # 125 | ############################################################################### 126 | ## Services 127 | ############################################################################### 128 | ## 129 | ## Check general system resources such as load average, cpu and memory 130 | ## usage. Each test specifies a resource, conditions and the action to be 131 | ## performed should a test fail. 132 | # 133 | # check system myhost.mydomain.tld 134 | # if loadavg (1min) > 4 then alert 135 | # if loadavg (5min) > 2 then alert 136 | # if memory usage > 75% then alert 137 | # if swap usage > 25% then alert 138 | # if cpu usage (user) > 70% then alert 139 | # if cpu usage (system) > 30% then alert 140 | # if cpu usage (wait) > 20% then alert 141 | # 142 | # 143 | ## Check if a file exists, checksum, permissions, uid and gid. In addition 144 | ## to alert recipients in the global section, customized alert can be sent to 145 | ## additional recipients by specifying a local alert handler. The service may 146 | ## be grouped using the GROUP option. More than one group can be specified by 147 | ## repeating the 'group name' statement. 148 | # 149 | # check file apache_bin with path /usr/local/apache/bin/httpd 150 | # if failed checksum and 151 | # expect the sum 8f7f419955cefa0b33a2ba316cba3659 then unmonitor 152 | # if failed permission 755 then unmonitor 153 | # if failed uid root then unmonitor 154 | # if failed gid root then unmonitor 155 | # alert security@foo.bar on { 156 | # checksum, permission, uid, gid, unmonitor 157 | # } with the mail-format { subject: Alarm! } 158 | # group server 159 | # 160 | # 161 | ## Check that a process is running, in this case Apache, and that it respond 162 | ## to HTTP and HTTPS requests. Check its resource usage such as cpu and memory, 163 | ## and number of children. If the process is not running, Monit will restart 164 | ## it by default. In case the service is restarted very often and the 165 | ## problem remains, it is possible to disable monitoring using the TIMEOUT 166 | ## statement. This service depends on another service (apache_bin) which 167 | ## is defined above. 168 | # 169 | # check process apache with pidfile /usr/local/apache/logs/httpd.pid 170 | # start program = "/etc/init.d/httpd start" with timeout 60 seconds 171 | # stop program = "/etc/init.d/httpd stop" 172 | # if cpu > 60% for 2 cycles then alert 173 | # if cpu > 80% for 5 cycles then restart 174 | # if totalmem > 200.0 MB for 5 cycles then restart 175 | # if children > 250 then restart 176 | # if loadavg(5min) greater than 10 for 8 cycles then stop 177 | # if failed host www.tildeslash.com port 80 protocol http 178 | # and request "/somefile.html" 179 | # then restart 180 | # if failed port 443 type tcpssl protocol http 181 | # with timeout 15 seconds 182 | # then restart 183 | # if 3 restarts within 5 cycles then timeout 184 | # depends on apache_bin 185 | # group server 186 | # 187 | # 188 | ## Check filesystem permissions, uid, gid, space and inode usage. Other services, 189 | ## such as databases, may depend on this resource and an automatically graceful 190 | ## stop may be cascaded to them before the filesystem will become full and data 191 | ## lost. 192 | # 193 | # check filesystem datafs with path /dev/sdb1 194 | # start program = "/bin/mount /data" 195 | # stop program = "/bin/umount /data" 196 | # if failed permission 660 then unmonitor 197 | # if failed uid root then unmonitor 198 | # if failed gid disk then unmonitor 199 | # if space usage > 80% for 5 times within 15 cycles then alert 200 | # if space usage > 99% then stop 201 | # if inode usage > 30000 then alert 202 | # if inode usage > 99% then stop 203 | # group server 204 | # 205 | # 206 | ## Check a file's timestamp. In this example, we test if a file is older 207 | ## than 15 minutes and assume something is wrong if its not updated. Also, 208 | ## if the file size exceed a given limit, execute a script 209 | # 210 | # check file database with path /data/mydatabase.db 211 | # if failed permission 700 then alert 212 | # if failed uid data then alert 213 | # if failed gid data then alert 214 | # if timestamp > 15 minutes then alert 215 | # if size > 100 MB then exec "/my/cleanup/script" as uid dba and gid dba 216 | # 217 | # 218 | ## Check directory permission, uid and gid. An event is triggered if the 219 | ## directory does not belong to the user with uid 0 and gid 0. In addition, 220 | ## the permissions have to match the octal description of 755 (see chmod(1)). 221 | # 222 | # check directory bin with path /bin 223 | # if failed permission 755 then unmonitor 224 | # if failed uid 0 then unmonitor 225 | # if failed gid 0 then unmonitor 226 | # 227 | # 228 | ## Check a remote host availability by issuing a ping test and check the 229 | ## content of a response from a web server. Up to three pings are sent and 230 | ## connection to a port and an application level network check is performed. 231 | # 232 | # check host myserver with address 192.168.1.1 233 | # if failed icmp type echo count 3 with timeout 3 seconds then alert 234 | # if failed port 3306 protocol mysql with timeout 15 seconds then alert 235 | # if failed url http://user:password@www.foo.bar:8080/?querystring 236 | # and content == 'action="j_security_check"' 237 | # then alert 238 | # 239 | # 240 | check process looker with pidfile /home/lookerops/looker/.tmp/looker.pid 241 | start program = "/etc/init.d/looker start" with timeout 300 seconds 242 | stop program = "/etc/init.d/looker stop" 243 | if failed host 0.0.0.0 port 9999 type tcpSSL protocol http with timeout 20 seconds for 3 cycles then restart 244 | ############################################################################### 245 | ## Includes 246 | ############################################################################### 247 | ## 248 | ## It is possible to include additional configuration parts from other files or 249 | ## directories. 250 | # 251 | include /etc/monit/conf.d/* 252 | # 253 | -------------------------------------------------------------------------------- /startup_scripts/systemd/README.md: -------------------------------------------------------------------------------- 1 | Systemd replaces the SysV init system. It is used with RHEL 7, CentOS 7, and others. 2 | 3 | The instructions on this page were tested on an AWS host running CentOS 7. 4 | 5 | ## Enabling Looker to start on boot 6 | To enable Looker to start on boot for a host which uses systemd, perform the following steps as root: 7 | 8 | First, save the [looker.service](https://raw.githubusercontent.com/looker/customer-scripts/master/startup_scripts/systemd/looker.service) file from this repository as /etc/systemd/system/looker.service 9 | 10 | You may need to customize the looker.service file if you are using a user other than "looker", or if 11 | Looker is not installed in /home/looker/looker. 12 | 13 | Second, adjust the file permissions: 14 | 15 | ``` 16 | chmod 664 /etc/systemd/system/looker.service 17 | ``` 18 | 19 | Force Looker to run in the foreground: 20 | 21 | In either the /home/looker/looker/looker startup script or in /home/looker/looker/lookerstart.cfg, a file you would need to create, set the --no-daemonize flag in the LOOKERARGS environment variable 22 | 23 | ``` 24 | LOOKERARGS="--no-daemonize --force-gcm-encryption" 25 | ``` 26 | or, if you are running a cluster, or have other custom args, something like 27 | ``` 28 | LOOKERARGS="--no-daemonize -d looker-db.yml --clustered -H 10.10.10.10 --shared-storage-dir /path/to/mounted/shared/storage --force-gcm-encryption" 29 | ``` 30 | 31 | Lastly, run the following commmands: 32 | 33 | ``` 34 | systemctl daemon-reload 35 | systemctl enable looker.service 36 | ``` 37 | 38 | ## Managing Looker 39 | 40 | To start the service: 41 | ``` 42 | systemctl start looker 43 | ``` 44 | Please note that it takes a couple of minutes for Looker to start. If you have a large HyperSQL database 45 | (see the files in the looker/.db directory) startup can take considerably longer. If so you may need to 46 | adjust the TimeoutStartSec setting in the looker.service file. 47 | 48 | To stop the service: 49 | ``` 50 | systemctl stop looker 51 | ``` 52 | 53 | To see the current status 54 | ``` 55 | systemctl status looker 56 | ``` 57 | -------------------------------------------------------------------------------- /startup_scripts/systemd/looker.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Looker Application 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/home/looker/looker/looker start 7 | ExecStop=/home/looker/looker/looker stop 8 | Type=simple 9 | PIDFile=/home/looker/looker/.tmp/looker.pid 10 | User=looker 11 | WorkingDirectory=/home/looker/looker 12 | TimeoutStartSec=500 13 | 14 | [Install] 15 | WantedBy=default.target 16 | --------------------------------------------------------------------------------