├── .gitignore ├── Dockerfile ├── README.md ├── config ├── SQLAPI-prod.js ├── WS-prod.js ├── app_config.sample.yml ├── cartodb.nginx.proxy.conf ├── database.yml ├── grunt_production.json └── varnish ├── create_user ├── setup_organization.sh └── startup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | config/app_config.yml -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:12.04 2 | RUN locale-gen en_US.UTF-8 &&\ 3 | update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 4 | RUN apt-get update &&\ 5 | apt-get install -q -y autoconf binutils-doc bison build-essential flex 6 | 7 | #apt-utils 8 | RUN apt-get install -q -y apt-utils 9 | 10 | #ruby-rvm 11 | RUN apt-get install -q -y ruby-rvm 12 | 13 | #varnish 14 | RUN apt-get install -q -y varnish 15 | 16 | #git 17 | RUN apt-get install -q -y git 18 | 19 | #apt tools 20 | RUN apt-get install -q -y python-software-properties 21 | 22 | RUN add-apt-repository ppa:cartodb/gcc &&\ 23 | apt-get update 24 | 25 | RUN apt-get install -q -y gcc-4.9 g++-4.9 26 | 27 | ENV CC=/usr/bin/gcc-4.9 28 | ENV CXX=/usr/bin/g++-4.9 29 | 30 | #postgresql 31 | RUN add-apt-repository ppa:cartodb/postgresql-9.5 && apt-get update 32 | 33 | #client packages 34 | RUN apt-get install -q -y libpq5 \ 35 | libpq-dev \ 36 | postgresql-client-9.5 \ 37 | postgresql-client-common 38 | #server packages 39 | RUN apt-get install -q -y postgresql-9.5 \ 40 | postgresql-contrib-9.5 \ 41 | postgresql-server-dev-9.5 \ 42 | postgresql-plpython-9.5 43 | 44 | #PostgreSQL Config 45 | RUN sed -i 's/\(peer\|md5\)/trust/' /etc/postgresql/9.5/main/pg_hba.conf 46 | 47 | #create users 48 | RUN service postgresql start && \ 49 | createuser publicuser --no-createrole --no-createdb --no-superuser -U postgres && \ 50 | createuser tileuser --no-createrole --no-createdb --no-superuser -U postgres && \ 51 | service postgresql stop 52 | 53 | #carto postgres extension 54 | RUN git clone https://github.com/CartoDB/cartodb-postgresql.git &&\ 55 | cd cartodb-postgresql &&\ 56 | PGUSER=postgres make install 57 | 58 | #GIS dependencies 59 | RUN apt-get upgrade -q -y && add-apt-repository ppa:cartodb/gis && apt-get update &&\ 60 | apt-get install -q -y proj proj-bin proj-data libproj-dev &&\ 61 | apt-get install -q -y libjson0 libjson0-dev python-simplejson &&\ 62 | apt-get install -q -y libgeos-c1v5 libgeos-dev &&\ 63 | apt-get install -q -y gdal-bin libgdal1-dev libgdal-dev &&\ 64 | apt-get install -q -y gdal2.1-static-bin 65 | 66 | #postgis 67 | RUN apt-get -q -y install libxml2-dev &&\ 68 | apt-get install -q -y liblwgeom-2.2.2 postgis postgresql-9.5-postgis-2.2 postgresql-9.5-postgis-scripts 69 | 70 | #postgis setup 71 | RUN service postgresql start && \ 72 | createdb -T template0 -O postgres -U postgres -E UTF8 template_postgis &&\ 73 | psql -U postgres template_postgis -c 'CREATE EXTENSION postgis;CREATE EXTENSION postgis_topology;' &&\ 74 | ldconfig &&\ 75 | service postgresql stop 76 | 77 | #redis 78 | RUN add-apt-repository ppa:cartodb/redis && apt-get update 79 | 80 | RUN apt-get install -q -y redis-server 81 | 82 | #nodejs 83 | RUN add-apt-repository ppa:cartodb/nodejs &&\ 84 | apt-get update &&\ 85 | apt-get install -q -y nodejs 86 | 87 | RUN apt-get install -q -y libpixman-1-0 libpixman-1-dev 88 | RUN apt-get install -q -y libcairo2-dev libjpeg-dev libgif-dev libpango1.0-dev 89 | 90 | #SQL API 91 | RUN git clone git://github.com/CartoDB/CartoDB-SQL-API.git &&\ 92 | cd CartoDB-SQL-API &&\ 93 | git checkout master &&\ 94 | npm install 95 | 96 | #MAPS API: 97 | RUN git clone git://github.com/CartoDB/Windshaft-cartodb.git &&\ 98 | cd Windshaft-cartodb &&\ 99 | git checkout master &&\ 100 | npm install -g yarn@0.27.5 &&\ 101 | yarn install 102 | 103 | #Ruby 104 | RUN apt-get install -q -y wget &&\ 105 | wget -O ruby-install-0.5.0.tar.gz https://github.com/postmodern/ruby-install/archive/v0.5.0.tar.gz &&\ 106 | tar -xzvf ruby-install-0.5.0.tar.gz &&\ 107 | cd ruby-install-0.5.0/ &&\ 108 | make install 109 | 110 | RUN apt-get -q -y install libreadline6-dev openssl &&\ 111 | ruby-install ruby 2.2.3 112 | 113 | ENV PATH=$PATH:/opt/rubies/ruby-2.2.3/bin 114 | 115 | RUN gem install bundler --version=1.17.3 &&\ 116 | gem install compass 117 | 118 | ENV RAILS_ENV production 119 | 120 | #Carto Editor 121 | RUN git clone --recursive https://github.com/CartoDB/cartodb.git &&\ 122 | cd cartodb &&\ 123 | wget -O /tmp/get-pip.py https://bootstrap.pypa.io/get-pip.py &&\ 124 | python /tmp/get-pip.py 125 | 126 | RUN apt-get install -q -y python-all-dev &&\ 127 | apt-get install -q -y imagemagick unp zip 128 | 129 | RUN cd cartodb &&\ 130 | bundle install &&\ 131 | npm install 132 | 133 | ENV CPLUS_INCLUDE_PATH=/usr/include/gdal 134 | ENV C_INCLUDE_PATH=/usr/include/gdal 135 | ENV PATH=$PATH:/usr/include/gdal 136 | 137 | RUN cd cartodb && pip install --no-use-wheel -r python_requirements.txt 138 | 139 | 140 | #Config Files 141 | ADD ./config/SQLAPI-prod.js \ 142 | /CartoDB-SQL-API/config/environments/production.js 143 | ADD ./config/WS-prod.js \ 144 | /Windshaft-cartodb/config/environments/production.js 145 | ADD ./config/app_config.yml /cartodb/config/app_config.yml 146 | ADD ./config/database.yml /cartodb/config/database.yml 147 | ADD ./config/grunt_production.json /cartodb/config/grunt_production.json 148 | 149 | RUN locale-gen en_US.UTF-8 150 | ENV LANG en_US.UTF-8 151 | ENV LANGUAGE en_US:en 152 | ENV LC_ALL en_US.UTF-8 153 | 154 | 155 | RUN cd cartodb &&\ 156 | export PATH=$PATH:$PWD/node_modules/grunt-cli/bin &&\ 157 | bundle install &&\ 158 | bundle exec grunt --environment production 159 | 160 | RUN service postgresql start && service redis-server start &&\ 161 | cd cartodb &&\ 162 | bundle exec rake db:create &&\ 163 | bundle exec rake db:migrate &&\ 164 | service postgresql stop && service redis-server stop 165 | 166 | 167 | ADD ./create_user /cartodb/script/create_user 168 | RUN service postgresql start && service redis-server start && \ 169 | bash -l -c "cd /cartodb && bash script/create_user" && \ 170 | service postgresql stop && service redis-server stop 171 | 172 | EXPOSE 3000 8080 8181 173 | 174 | ENV GDAL_DATA /usr/share/gdal/2.1 175 | 176 | ADD ./startup.sh /opt/startup.sh 177 | ADD ./config/varnish /etc/default/varnish 178 | 179 | VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"] 180 | 181 | CMD ["/bin/bash", "/opt/startup.sh"] 182 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-cartodb 2 | This is a dockerized production Carto(DB) installation, based on the official [Carto Installation Documentation](http://cartodb.readthedocs.io/en/latest/install.html), using the latest dependencies including ogr2ogr2.1. 3 | 4 | You should be able to map most of the steps in the `Dockerfile` with those on the install documentation. The steps below were written with a Digital Ocean droplet (docker pre-installed) in mind. 5 | 6 | ![dockerizecarto](https://cloud.githubusercontent.com/assets/1833820/22806442/1703bcac-eef0-11e6-8826-33a126932d23.png) 7 | 8 | 9 | ## Production vs Development 10 | This Dockerfile assumes you want to run Carto with SSL, which requires a few configuration steps beyond just building the docker container. The biggest difference from other Dockerfiles is setting the `production` environment variables, and then adding ssl certificates to the nginx configuration. 11 | 12 | This build also makes use of Docker volumes, so that the the data can persist. This should allow for an easier upgrade path when new versions of the core components are release. 13 | 14 | ## How to Build 15 | 16 | ### Get yourself a Droplet 17 | We have had success installing Carto in a Docker container on a Digital Ocean droplet with 8GB of Ram, 80GB Storage and 4 cores, which runs $80/month. You can choose an Ubuntu 16.04 image with Docker preinstalled and save yourself some time. SSH into that bad boy and get ready to Docker. 18 | 19 | ### Edit the sample app_config.yml 20 | You will need a FQDN with an A record pointing to your server's IP address. You need to edit `config/app_config.sample.yml`, and replace every instance of 'yourdomain.com' with your domain name and save the file as `app_config.yml`. The dockerfile will insert this into the new container during the build process. 21 | 22 | 23 | ### Build the Container 24 | Go make a sandwich and watch some youtube videos, this will take a while... (About an hour as of the time I wrote this) 25 | ``` 26 | git clone https://github.com/chriswhong/docker-cartodb.git 27 | docker build -t="cartodb" docker-cartodb/ 28 | ``` 29 | ### Run the Container 30 | This command runs the container with the three main services mapped to the host machine. `3000` for the frontend, `8080` for the Windshaft Map Tiler (Maps API), and `8181` for the SQL API. 31 | Use `docker run -d -p 3000:3000 -p 8080:8080 -p 8181:8181 cartodb` the first time you run it. 32 | 33 | If you are replacing an existing container built with this image, add the `--volumes from` flag like `docker run --volumes-from {id of old container} -d -p 3001:3000 -p 8081:8080 -p 8182:8181 cartodb` 34 | 35 | You can't connect from the outside world until you setup nginx to forward specific URLs to the three ports 36 | 37 | ### Configure Nginx 38 | 39 | Install nginx `apt-get install nginx` and then copy `config/cartodb.nginx.proxy.conf` from this repo to `/etc/nginx/conf.d/`. 40 | 41 | Use `certbot-auto` to quickly install SSL certificates for your domain. Take note of where it tells you it stored the new SSL certificates 42 | 43 | Edit the file to include your production domain name and the paths to the SSL certificates. 44 | 45 | Restart nginx `service nginx restart` 46 | 47 | ### Users 48 | The Dockerfile will create a user named `admin` with a default password of `pass1234`. You should change this when you first login. 49 | 50 | To make more users, run the `create_user` script from inside the running container. `docker exec -it {containerid} /bin/bash` The script is in `/cartodb/script/create_user` edit it to set the new username and password, then run it `sh create_user` 51 | 52 | ### Add more map layers to a User's Account 53 | User accounts will only be allowed to add 4 layers to a map in the editor by default, you can change this by using the rails console. 54 | First get to the command line in your container: `docker exec -it {containerid} /bin/bash` 55 | ``` 56 | cd cartodb 57 | bundle exec rails c 58 | u = User.find(username:'username') 59 | u.max_layers = 15 60 | u.save 61 | ``` 62 | 63 | ### Revert to old Editor 64 | We are using this carto server strictly as a tile/data service, so the builder is not needed, but is enabled by default. To disable it, you must run SQL `update users set builder_enabled = false where username = 'myusername';` To run this sql, run a command prompt in the running container `docker exec -it {containerid} /bin/bash` Once you are in, switch to postgres user `su postgres` and use psql to connect `psql -d carto_db_production` 65 | 66 | ### Enable Private Maps 67 | 68 | `UPDATE users SET private_maps_enabled = 't';` 69 | 70 | ### To enable GZIP 71 | This can also be done in nginx, you just need to enable gzip and add the mime types that carto uses. 72 | 73 | ### To use carto-served vector tiles 74 | This is unrelated to carto in Docker, but It's exciting so I thought I would share it. [See this gist](http://bl.ocks.org/chriswhong/2695b75fd1936bd034df83c91738648d) 75 | 76 | ## Attribution 77 | First and foremost, thank you to the Carto team for such a great product that is also open source! 78 | This Dockerfile was inspired by and largely based on [Stefan Verhoeven's image](https://github.com/sverhoeven/docker-cartodb). I could not get it working and descided to start over using the official installation docs. All of the configs are borrowed directly from his. 79 | 80 | ## Pull requests and issues welcomed! 81 | If this doesn't work for you, please open an issue and let's figure out why. 82 | -------------------------------------------------------------------------------- /config/SQLAPI-prod.js: -------------------------------------------------------------------------------- 1 | // In case the base_url has a :user param the username will be the one specified in the URL, 2 | // otherwise it will fallback to extract the username from the host header. 3 | module.exports.base_url = '(?:/api/:version|/user/:user/api/:version)'; 4 | // If useProfiler is true every response will be served with an 5 | // X-SQLAPI-Profile header containing elapsed timing for various 6 | // steps taken for producing the response. 7 | module.exports.useProfiler = true; 8 | module.exports.log_format = '[:date] :remote-addr :method :req[Host]:url :status :response-time ms -> :res[Content-Type] (:res[X-SQLAPI-Profiler])'; 9 | // If log_filename is given logs will be written there, in append mode. Otherwise stdout is used (default). 10 | // Log file will be re-opened on receiving the HUP signal 11 | module.exports.log_filename = 'logs/cartodb-sql-api.log'; 12 | // Regular expression pattern to extract username 13 | // from hostname. Must have a single grabbing block. 14 | module.exports.user_from_host = '^([^\\.]+)\\.'; 15 | module.exports.node_port = 8080; 16 | module.exports.node_host = '0.0.0.0'; 17 | // idle socket timeout, in miliseconds 18 | module.exports.node_socket_timeout = 600000; 19 | module.exports.environment = 'production'; 20 | module.exports.db_base_name = 'cartodb_user_<%= user_id %>_db'; 21 | // Supported labels: 'user_id' (read from redis) 22 | module.exports.db_user = 'cartodb_user_<%= user_id %>'; 23 | // Supported labels: 'user_id', 'user_password' (both read from redis) 24 | module.exports.db_user_pass = '<%= user_password %>' 25 | // Name of the anonymous PostgreSQL user 26 | module.exports.db_pubuser = 'publicuser'; 27 | // Password for the anonymous PostgreSQL user 28 | module.exports.db_pubuser_pass = 'public'; 29 | module.exports.db_host = 'localhost'; 30 | module.exports.db_port = '5432'; 31 | module.exports.db_batch_port = '5432'; 32 | module.exports.finished_jobs_ttl_in_seconds = 2 * 3600; // 2 hours 33 | // Max database connections in the pool 34 | // Subsequent connections will wait for a free slot. 35 | // NOTE: not used by OGR-mediated accesses 36 | module.exports.db_pool_size = 500; 37 | // Milliseconds before a connection is removed from pool 38 | module.exports.db_pool_idleTimeout = 30000; 39 | // Milliseconds between idle client checking 40 | module.exports.db_pool_reapInterval = 1000; 41 | // max number of bytes for a row, when exceeded the query will throw an error 42 | //module.exports.db_max_row_size = 10 * 1024 * 1024; 43 | // allows to use an object to connect with node-postgres instead of a connection string 44 | //module.exports.db_use_config_object = true; 45 | // requires enabling db_use_config_object=true 46 | // allows to enable/disable keep alive for database connections 47 | // by default is not enabled 48 | //module.exports.db_keep_alive = { 49 | // enabled: true, 50 | // initialDelay: 5000 51 | //}; 52 | module.exports.redis_host = '127.0.0.1'; 53 | module.exports.redis_port = 6379; 54 | module.exports.redisPool = 50; 55 | module.exports.redisIdleTimeoutMillis = 100; 56 | module.exports.redisReapIntervalMillis = 10; 57 | module.exports.redisLog = false; 58 | // Max number of entries in the query tables cache 59 | module.exports.tableCacheMax = 8192; 60 | // Max age of query table cache items, in milliseconds 61 | module.exports.tableCacheMaxAge = 1000*60*10; 62 | // Temporary directory, make sure it is writable by server user 63 | module.exports.tmpDir = '/tmp'; 64 | // change ogr2ogr command or path 65 | module.exports.ogr2ogrCommand = 'ogr2ogr'; 66 | // Optional statsd support 67 | module.exports.statsd = { 68 | host: 'localhost', 69 | port: 8125, 70 | prefix: 'dev.:host.', 71 | cacheDns: true 72 | // support all allowed node-statsd options 73 | }; 74 | module.exports.health = { 75 | enabled: true, 76 | username: 'development', 77 | query: 'select 1' 78 | }; 79 | module.exports.disabled_file = 'pids/disabled'; 80 | -------------------------------------------------------------------------------- /config/WS-prod.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | environment: 'production' 3 | ,port: 8181 4 | ,host: '0.0.0.0' 5 | // Size of the threadpool which can be used to run user code and get notified in the loop thread 6 | // Its default size is 4, but it can be changed at startup time (the absolute maximum is 128). 7 | // See http://docs.libuv.org/en/latest/threadpool.html 8 | ,uv_threadpool_size: undefined 9 | // Regular expression pattern to extract username 10 | // from hostname. Must have a single grabbing block. 11 | ,user_from_host: '^([^\\.]+)\\.' 12 | 13 | // Base URLs for the APIs 14 | // 15 | // See http://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API 16 | // 17 | // Base url for the Templated Maps API 18 | // "/api/v1/map/named" is the new API, 19 | // "/tiles/template" is for compatibility with versions up to 1.6.x 20 | ,base_url_templated: '(?:/api/v1/map/named|/user/:user/api/v1/map/named|/tiles/template)' 21 | // Base url for the Detached Maps API 22 | // "maps" is the the new API, 23 | // "tiles/layergroup" is for compatibility with versions up to 1.6.x 24 | ,base_url_detached: '(?:/api/v1/map|/user/:user/api/v1/map|/tiles/layergroup)' 25 | // Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status. 26 | // 27 | // This URLs depend on how `base_url_detached` and `user_from_host` are configured: the application can be 28 | // configured to accept request with the {user} in the header host or in the request path. 29 | // It also might depend on the configured cdn_url via `serverMetadata.cdn_url`. 30 | // 31 | // This template allows to make the endpoints generation more flexible, the template exposes the following params: 32 | // 1. {{=it.cdn_url}}: will be used when `serverMetadata.cdn_url` exists. 33 | // 2. {{=it.user}}: will use the username as extraced from `user_from_host` or `base_url_detached`. 34 | // 3. {{=it.port}}: will use the `port` from this very same configuration file. 35 | //,serverMetadata : { cdn_url : {http: '127.0.0.1', https: '127.0.0.1'}} 36 | ,resources_url_templates: { 37 | http: 'http://cartodb.localhost:{{=it.port}}/user/{{=it.user}}/api/v1/map', 38 | https: 'https://localhost.lan:user/{{=it.user}}/api/v1/map' 39 | } 40 | // Maximum number of connections for one process 41 | // 128 is a good value with a limit of 1024 open file descriptors 42 | ,maxConnections:128 43 | // Maximum number of templates per user. Unlimited by default. 44 | ,maxUserTemplates:1024 45 | // Seconds since "last creation" before a detached 46 | // or template instance map expires. Or: how long do you want 47 | // to be able to navigate the map without a reload ? 48 | // Defaults to 7200 (2 hours) 49 | ,mapConfigTTL: 7200 50 | // idle socket timeout, in milliseconds 51 | ,socket_timeout: 600000 52 | ,enable_cors: true 53 | ,cache_enabled: false 54 | ,log_format: ':req[X-Real-IP] :method :req[Host]:url :status :response-time ms -> :res[Content-Type] (:res[X-Tiler-Profiler])' 55 | // If log_filename is given logs will be written 56 | // there, in append mode. Otherwise stdout is used (default). 57 | // Log file will be re-opened on receiving the HUP signal 58 | ,log_filename: undefined 59 | // Templated database username for authorized user 60 | // Supported labels: 'user_id' (read from redis) 61 | ,postgres_auth_user: 'cartodb_user_<%= user_id %>' 62 | // Templated database password for authorized user 63 | // Supported labels: 'user_id', 'user_password' (both read from redis) 64 | ,postgres_auth_pass: '<%= user_password %>' 65 | ,postgres: { 66 | // Parameters to pass to datasource plugin of mapnik 67 | // See http://github.com/mapnik/mapnik/wiki/PostGIS 68 | type: "postgis", 69 | user: "publicuser", 70 | password: "public", 71 | host: '127.0.0.1', 72 | port: 5432, 73 | extent: "-20037508.3,-20037508.3,20037508.3,20037508.3", 74 | /* experimental 75 | geometry_field: "the_geom", 76 | extent: "-180,-90,180,90", 77 | srid: 4326, 78 | */ 79 | // max number of rows to return when querying data, 0 means no limit 80 | row_limit: 65535, 81 | simplify_geometries: true, 82 | use_overviews: true, // use overviews to retrieve raster 83 | /* 84 | * Set persist_connection to false if you want 85 | * database connections to be closed on renderer 86 | * expiration (1 minute after last use). 87 | * Setting to true (the default) would never 88 | * close any connection for the server's lifetime 89 | */ 90 | persist_connection: false, 91 | max_size: 500 92 | } 93 | ,mapnik_version: undefined 94 | ,mapnik_tile_format: 'png8:m=h' 95 | ,statsd: { 96 | host: 'localhost', 97 | port: 8125, 98 | prefix: 'dev.', 99 | cacheDns: true 100 | // support all allowed node-statsd options 101 | } 102 | ,renderer: { 103 | // Milliseconds since last access before renderer cache item expires 104 | cache_ttl: 60000, 105 | statsInterval: 5000, // milliseconds between each report to statsd about number of renderers and mapnik pool status 106 | mapnik: { 107 | // The size of the pool of internal mapnik backend 108 | // This pool size is per mapnik renderer created in Windshaft's RendererFactory 109 | // See https://github.com/CartoDB/Windshaft/blob/master/lib/windshaft/renderers/renderer_factory.js 110 | // Important: check the configuration of uv_threadpool_size to use suitable value 111 | poolSize: 8, 112 | 113 | // Metatile is the number of tiles-per-side that are going 114 | // to be rendered at once. If all of them will be requested 115 | // we'd have saved time. If only one will be used, we'd have 116 | // wasted time. 117 | metatile: 2, 118 | 119 | // tilelive-mapnik uses an internal cache to store tiles/grids 120 | // generated when using metatile. This options allow to tune 121 | // the behaviour for that internal cache. 122 | metatileCache: { 123 | // Time an object must stay in the cache until is removed 124 | ttl: 0, 125 | // Whether an object must be removed after the first hit 126 | // Usually you want to use `true` here when ttl>0. 127 | deleteOnHit: false 128 | }, 129 | 130 | // Override metatile behaviour depending on the format 131 | formatMetatile: { 132 | png: 2, 133 | 'grid.json': 1 134 | }, 135 | 136 | // Buffer size is the tickness in pixel of a buffer 137 | // around the rendered (meta?)tile. 138 | // 139 | // This is important for labels and other marker that overlap tile boundaries. 140 | // Setting to 128 ensures no render artifacts. 141 | // 64 may have artifacts but is faster. 142 | // Less important if we can turn metatiling on. 143 | bufferSize: 64, 144 | 145 | // SQL queries will be wrapped with ST_SnapToGrid 146 | // Snapping all points of the geometry to a regular grid 147 | snapToGrid: false, 148 | 149 | // SQL queries will be wrapped with ST_ClipByBox2D 150 | // Returning the portion of a geometry falling within a rectangle 151 | // It will only work if snapToGrid is enabled 152 | clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 153 | 154 | limits: { 155 | // Time in milliseconds a render request can take before it fails, some notes: 156 | // - 0 means no render limit 157 | // - it considers metatiling, naive implementation: (render timeout) * (number of tiles in metatile) 158 | render: 0, 159 | // As the render request will finish even if timed out, whether it should be placed in the internal 160 | // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve 161 | // the same tile will result in an immediate response, however that will use a lot of more application 162 | // memory. If we want to enforce this behaviour we have to implement a cache eviction policy for the 163 | // internal cache. 164 | cacheOnTimeout: true 165 | }, 166 | 167 | geojson: { 168 | dbPoolParams: { 169 | // maximum number of resources to create at any given time 170 | size: 16, 171 | // max milliseconds a resource can go unused before it should be destroyed 172 | idleTimeout: 3000, 173 | // frequency to check for idle resources 174 | reapInterval: 1000 175 | }, 176 | 177 | // SQL queries will be wrapped with ST_ClipByBox2D 178 | // Returning the portion of a geometry falling within a rectangle 179 | // It will only work if snapToGrid is enabled 180 | clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 181 | // geometries will be simplified using ST_RemoveRepeatedPoints 182 | // which cost is no more expensive than snapping and results are 183 | // much closer to the original geometry 184 | removeRepeatedPoints: false // this requires postgis >=2.2 185 | } 186 | 187 | }, 188 | http: { 189 | timeout: 2000, // the timeout in ms for a http tile request 190 | proxy: undefined, // the url for a proxy server 191 | whitelist: [ // the whitelist of urlTemplates that can be used 192 | '.*', // will enable any URL 193 | 'http://{s}.example.com/{z}/{x}/{y}.png' 194 | ], 195 | // image to use as placeholder when urlTemplate is not in the whitelist 196 | // if provided the http renderer will use it instead of throw an error 197 | fallbackImage: { 198 | type: 'fs', // 'fs' and 'url' supported 199 | src: __dirname + '/../../assets/default-placeholder.png' 200 | } 201 | }, 202 | torque: { 203 | dbPoolParams: { 204 | // maximum number of resources to create at any given time 205 | size: 16, 206 | // max milliseconds a resource can go unused before it should be destroyed 207 | idleTimeout: 3000, 208 | // frequency to check for idle resources 209 | reapInterval: 1000 210 | } 211 | } 212 | } 213 | // anything analyses related 214 | ,analysis: { 215 | // batch configuration 216 | batch: { 217 | // Inline execution avoid the use of SQL API as batch endpoint 218 | // When set to true it will run all analysis queries in series, with a direct connection to the DB 219 | // This might be useful for: 220 | // - testing 221 | // - running an standalone server without any dependency on external services 222 | inlineExecution: false, 223 | // where the SQL API is running, it will use a custom Host header to specify the username. 224 | endpoint: 'http://127.0.0.1:8080/api/v2/sql/job', 225 | // the template to use for adding the host header in the batch api requests 226 | hostHeaderTemplate: '{{=it.username}}.localhost.lan' 227 | } 228 | } 229 | ,millstone: { 230 | // Needs to be writable by server user 231 | cache_basedir: '/tmp/cdb-tiler-dev/millstone-dev' 232 | } 233 | ,redis: { 234 | host: '127.0.0.1', 235 | port: 6379, 236 | // Max number of connections in each pool. 237 | // Users will be put on a queue when the limit is hit. 238 | // Set to maxConnection to have no possible queues. 239 | // There are currently 2 pools involved in serving 240 | // windshaft-cartodb requests so multiply this number 241 | // by 2 to know how many possible connections will be 242 | // kept open by the server. The default is 50. 243 | max: 50, 244 | returnToHead: true, // defines the behaviour of the pool: false => queue, true => stack 245 | idleTimeoutMillis: 1, // idle time before dropping connection 246 | reapIntervalMillis: 1, // time between cleanups 247 | slowQueries: { 248 | log: true, 249 | elapsedThreshold: 200 250 | }, 251 | slowPool: { 252 | log: true, // whether a slow acquire must be logged or not 253 | elapsedThreshold: 25 // the threshold to determine an slow acquire must be reported or not 254 | }, 255 | emitter: { 256 | statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd 257 | }, 258 | unwatchOnRelease: false, // Send unwatch on release, see http://github.com/CartoDB/Windshaft-cartodb/issues/161 259 | noReadyCheck: true // Check `no_ready_check` at https://github.com/mranney/node_redis/tree/v0.12.1#overloading 260 | } 261 | // For more details about this options check https://nodejs.org/api/http.html#http_new_agent_options 262 | ,httpAgent: { 263 | keepAlive: true, 264 | keepAliveMsecs: 1000, 265 | maxSockets: 25, 266 | maxFreeSockets: 256 267 | } 268 | ,varnish: { 269 | host: 'localhost', 270 | port: 6082, // the por for the telnet interface where varnish is listening to 271 | http_port: 6081, // the port for the HTTP interface where varnish is listening to 272 | purge_enabled: false, // whether the purge/invalidation mechanism is enabled in varnish or not 273 | secret: 'xxx', 274 | ttl: 86400, 275 | layergroupTtl: 86400 // the max-age for cache-control header in layergroup responses 276 | } 277 | // this [OPTIONAL] configuration enables invalidating by surrogate key in fastly 278 | ,fastly: { 279 | // whether the invalidation is enabled or not 280 | enabled: false, 281 | // the fastly api key 282 | apiKey: 'wadus_api_key', 283 | // the service that will get surrogate key invalidation 284 | serviceId: 'wadus_service_id' 285 | } 286 | // If useProfiler is true every response will be served with an 287 | // X-Tiler-Profile header containing elapsed timing for various 288 | // steps taken for producing the response. 289 | ,useProfiler:true 290 | // Settings for the health check available at /health 291 | ,health: { 292 | enabled: false, 293 | username: 'localhost', 294 | z: 0, 295 | x: 0, 296 | y: 0 297 | } 298 | ,disabled_file: 'pids/disabled' 299 | 300 | // Use this as a feature flags enabling/disabling mechanism 301 | ,enabledFeatures: { 302 | // whether it should intercept tile render errors an act based on them, enabled by default. 303 | onTileErrorStrategy: true, 304 | // whether the affected tables for a given SQL must query directly postgresql or use the SQL API 305 | cdbQueryTablesFromPostgres: true, 306 | // whether in mapconfig is available stats & metadata for each layer 307 | layerMetadata: true 308 | 309 | } 310 | }; 311 | 312 | module.exports = config; 313 | -------------------------------------------------------------------------------- /config/app_config.sample.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | # If uncommented, most images like static map previews and twitter card image urls will use this CDN urls 3 | #cdn_url: 4 | # http: "http.cdn.host" 5 | # https: "https.cdn.host" 6 | http_client_logs: true 7 | ogr2ogr: 8 | binary: 'which ogr2ogr2.1' 9 | csv_guessing: true 10 | debug_assets: true 11 | mandatory_keys: [layer_opts, sql_api, varnish_management, redis, session_domain] 12 | session_domain: 'yourdomain.com' 13 | # If activated, urls will use usernames in format //SESSION_DOMAIN/user/USERNAME and ignore subdomains if present 14 | subdomainless_urls: true 15 | http_port: # 3000 # nil|integer. HTTP port to use when building urls. Leave empty to use default (80) 16 | https_port: # nil|integer. HTTPS port to use when building urls. Leave empty to use default (443) 17 | secret_token: '71c2b25921b84a1cb21c71503ab8fb23' 18 | account_host: 'yourdomain.com' 19 | account_path: '/account' 20 | vizjson_cache_domains: ['.localhost'] 21 | data_library: 22 | username: 'common-data' 23 | path: '/data-library' 24 | disable_file: '~/disable' 25 | watcher: 26 | ttl: 60 27 | tiler: 28 | filter: 'mapnik' 29 | internal: 30 | protocol: 'http' 31 | domain: '' 32 | port: '8181' 33 | host: '127.0.0.1' 34 | verifycert: false 35 | private: 36 | protocol: 'https' 37 | domain: 'yourdomain.com' 38 | port: '443' 39 | verifycert: false 40 | public: 41 | protocol: 'https' 42 | domain: 'yourdomain.com' 43 | port: '443' 44 | verifycert: false 45 | sql_api: 46 | private: 47 | protocol: 'https' 48 | domain: 'yourdomain.com' 49 | endpoint: '/api/v2/sql' 50 | port: 443 51 | public: 52 | protocol: 'https' 53 | domain: 'yourdomain.com' 54 | endpoint: '/api/v2/sql' 55 | port: 443 56 | api_requests_service_url: '' 57 | developers_host: 'http://developers.cartodb.localhost:3000' 58 | google_analytics: 59 | primary: '' 60 | embeds: '' 61 | domain: '' 62 | rollbar_api_key: '' 63 | tumblr: 64 | api_key: '' 65 | trackjs: 66 | enabled: false 67 | customer: '' 68 | app_keys: 69 | editor: '' 70 | embeds: '' 71 | facebook: 72 | app_id: '' 73 | admins: '' 74 | hubspot: '' 75 | segment: 76 | api_key: 77 | common_data: 78 | protocol: 'https' 79 | username: 'common-data' 80 | base_url: 'https://common-data.carto.com' 81 | format: 'shp' 82 | generate_every: 86400 83 | explore_api: 84 | username: '' 85 | reports: 86 | mail_to: '' 87 | mailer: 88 | from: 'cartodb.localhost ' 89 | address: '' 90 | port: '' 91 | user_name: '' 92 | password: '' 93 | authentication: '' 94 | enable_starttls_auto: '' 95 | varnish_management: 96 | critical: false 97 | host: '127.0.0.1' 98 | port: 6082 99 | purge_command: 'purge' 100 | retries: 5 101 | timeout: 5 102 | # 'warning' or 'error' 103 | trigger_verbose: true 104 | invalidation_service: 105 | enabled: false 106 | host: '127.0.0.1' 107 | port: 3142 108 | retries: 5 # number of retries before considering failure 109 | critical: false # either the failure is considered an error or a warning 110 | timeout: 5 # socket timeout 111 | trigger_verbose: true 112 | redis: 113 | host: '127.0.0.1' 114 | port: 6379 115 | connect_timeout: 2 116 | read_timeout: 3 117 | write_timeout: 5 118 | databases: 119 | tables_metadata: 0 120 | api_credentials: 3 121 | users_metadata: 5 122 | redis_migrator_logs: 6 123 | org_metadata_api: 124 | host: 'localhost.lan' 125 | port: '3000' 126 | username: "extension" 127 | password: "elephant" 128 | timeout: 10 129 | superadmin: 130 | username: "superadmin" 131 | password: "monkey" 132 | geocoder: 133 | #force_batch: true 134 | #disable_cache: true 135 | app_id: '' 136 | token: '' 137 | mailto: '' 138 | base_url: '' 139 | non_batch_base_url: '' 140 | internal: 141 | username: '' 142 | api_key: '' 143 | cache: 144 | base_url: '' 145 | api_key: '' 146 | table_name: '' 147 | user_migrator: 148 | user_exports_folder: '/tmp/user_exports' 149 | user_imports_folder: '/tmp/user_imports' 150 | s3: 151 | access_key_id: '' 152 | secret_access_key: '' 153 | bucket_name: '' 154 | url_ttl: 7200 155 | async_long_uploads: false 156 | uploads_path: 'public/uploads' 157 | exporter: 158 | exporter_temporal_folder: '/tmp/exporter' 159 | s3: 160 | access_key_id: '' 161 | secret_access_key: '' 162 | bucket_name: '' 163 | url_ttl: 7200 164 | async_long_uploads: false 165 | uploads_path: 'public/uploads' # including 'uploads' assumes public path. Absolute path example: /tmp/exports/downloads 166 | importer: 167 | blacklisted_ip_addr: [] 168 | content_guessing: # Depends on geocoding 169 | enabled: false # Disabled if false or not present 170 | threshold: 0.9 # 90% or more matches 171 | minimum_entropy: 0.9 # Normalized entropy, between 0.0 and 1.0. See http://en.wikipedia.org/wiki/Entropy_(information_theory) 172 | sample_size: 400 # +-5% error. See http://en.wikipedia.org/wiki/Sample_size_determination#Estimating_proportions_and_means 173 | s3: 174 | access_key_id: 175 | secret_access_key: 176 | bucket_name: 177 | url_ttl: 178 | async_long_uploads: false 179 | proxy_uri: 180 | use_ssl: True 181 | 182 | unp_temporal_folder: '/tmp/imports/' 183 | # It must end in `/uploads` and be accessible via HTTP, if relative will default to Rails.Root/#{uploads_path} 184 | uploads_path: 'public/uploads' 185 | error_track: 186 | url: 'https://viz2.carto.com/api/v1/sql' 187 | percent_users: 10 188 | # graphite endpoint used to post frontend stats 189 | graphite_public: 190 | host: "" 191 | port: 192 | layer_opts: 193 | public_opts: ["type", "active", "query", "opacity", "auto_bound", 194 | "interactivity", "debug", "visible", "tiler_domain", 195 | "tiler_port", "tiler_protocol", "sql_domain", "sql_port", 196 | "sql_protocol", "extra_params", "table_name", 197 | "user_name", "style_version", "tile_style", "query_wrapper"] 198 | default_tile_styles: 199 | point: "{\n marker-fill: #FF6600;\n marker-opacity: 0.9;\n marker-width: 12;\n marker-line-color: white;\n marker-line-width: 3;\n marker-line-opacity: 0.9;\n marker-placement: point;\n marker-type: ellipse;\n marker-allow-overlap: true;\n}" 200 | geometry: "{\n // points\n [mapnik-geometry-type=point] {\n marker-fill: #FF6600;\n marker-opacity: 1;\n marker-width: 12;\n marker-line-color: white;\n marker-line-width: 3;\n marker-line-opacity: 0.9;\n marker-placement: point;\n marker-type: ellipse;marker-allow-overlap: true;\n }\n\n //lines\n [mapnik-geometry-type=linestring] {\n line-color: #FF6600; \n line-width: 2; \n line-opacity: 0.7;\n }\n\n //polygons\n [mapnik-geometry-type=polygon] {\n polygon-fill:#FF6600;\n polygon-opacity: 0.7;\n line-opacity:1;\n line-color: #FFFFFF;\n }\n }" 201 | polygon: "{\n polygon-fill:#FF6600;\n polygon-opacity: 0.7;\n line-opacity:1;\n line-color: #FFFFFF;\n}" 202 | multipolygon: "{\n polygon-fill:#FF6600;\n polygon-opacity: 0.7;\n line-opacity:1;\n line-color: #FFFFFF;\n}" 203 | multilinestring: "{\n line-color:#FF6600;\n line-width:1;\n line-opacity: 0.7;\n}" 204 | data: 205 | kind: "carto" 206 | options: 207 | # attribution: 'CARTO attribution' 208 | query: "" 209 | opacity: 0.99 210 | auto_bound: false 211 | interactivity: "cartodb_id" 212 | debug: false 213 | visible: true 214 | tiler_domain: "cartodb.localhost" 215 | tiler_port: "8181" 216 | tiler_protocol: "http" 217 | sql_domain: "cartodb.localhost" 218 | sql_port: "8080" 219 | sql_protocol: "http" 220 | extra_params: { cache_policy: 'persist' } 221 | tile_style_history: [] 222 | style_version: "2.1.1" 223 | infowindow: 224 | template_name: "table/views/infowindow_light" 225 | background: 226 | kind: "background" 227 | options: { color: '#ffffff' } 228 | cartodb_com_hosted: false 229 | cartodb_central_domain_name: 'yourdomain.com' 230 | aws: 231 | s3: 232 | access_key_id: "test" 233 | secret_access_key: "test" 234 | assets: 235 | s3_bucket_name: "tests" 236 | max_file_size: 5242880 # 5.megabytes 237 | app_assets: 238 | asset_host: "//cartodb-libs.global.ssl.fastly.net/cartodbui" 239 | avatars: 240 | gravatar_enabled: true 241 | base_url: '//cartodb-libs.global.ssl.fastly.net/cartodbui/assets/unversioned/images/avatars' 242 | kinds: ['ghost', 'marker', 'mountain', 'pacman', 'planet', 'star'] 243 | colors: ['green', 'orange', 'red', 'yellow'] 244 | dropbox_api_key: "" 245 | gdrive: 246 | api_key: "" 247 | app_id: "" 248 | # This enables a support chat within editor 249 | # Use your Olark api id to enable it. If you remove this entry or don't define an app key, it won't be activated. 250 | olark: 251 | app_id: '' 252 | enforce_non_empty_layer_css: false 253 | users_dumps: 254 | service: 255 | port: 00000 256 | http_header_authentication: 257 | header: # name of the trusted, safe header that your server adds to the request 258 | field: # 'email' / 'username' / 'id' / 'auto' (autodetection) 259 | autocreation: # true / false (true requires field to be email) 260 | oauth: 261 | # If the client_id/app_key is not set won't appear at the UI. @see application_helper.rb -> frontend_config 262 | # Must be the same as CartoDB::Datasources::xxxx DATASOURCE_NAME constants 263 | gdrive: 264 | application_name: '' 265 | client_id: '' 266 | client_secret: '' 267 | callback_url: 'https://carto.com' 268 | # google_plus: 269 | # client_id: '' 270 | # cookie_policy: 'single_host_origin' 271 | # cookie_policy: 'https://cartodb-staging.com' 272 | github: 273 | client_id: '' 274 | client_secret: '' 275 | dropbox: 276 | app_key: '' 277 | app_secret: '' 278 | callback_url: '' 279 | box: 280 | application_name: '' 281 | client_id: '' 282 | client_secret: '' 283 | box_host: "app.box.com" 284 | instagram: 285 | app_key: '' 286 | app_secret: '' 287 | callback_url: '' 288 | # Mailchimp datasource. Setup at https://admin.mailchimp.com/account/oauth2/ then fill here. 289 | # If fields are present but empty, option won't appear at editor import window 290 | mailchimp: 291 | app_key: '' 292 | app_secret: '' 293 | callback_url: '' 294 | datasource_search: 295 | # Must be the same as CartoDB::Datasources::xxxx DATASOURCE_NAME constants 296 | twitter_search: 297 | standard: 298 | auth_required: false 299 | username: '' 300 | password: '' 301 | search_url: 'http://fake.url.nil' 302 | ratelimit_active: true 303 | ratelimit_concurrency: 8 304 | ratelimit_ttl: 4 305 | ratelimit_wait_secs: 0.5 306 | customized_user_list: [] 307 | customized_orgs_list: [] 308 | entity_to_config_map: [] # { user_or_org_name: 'custom_config_name'} 309 | customized: 310 | custom1: 311 | auth_required: false 312 | username: '' 313 | password: '' 314 | search_url: 'http://fake.url.nil' 315 | ratelimit_active: false 316 | ratelimit_concurrency: 3 317 | ratelimit_ttl: 4 318 | ratelimit_wait_secs: 0.1 319 | basemaps: 320 | Nokia: 321 | normal_day: 322 | url: 'https://maps.nlp.nokia.com/maptiler/v2/maptile/newest/normal.day/{z}/{x}/{y}/256/png8?lg=eng&token=A7tBPacePg9Mj_zghvKt9Q&app_id=KuYppsdXZznpffJsKT24' 323 | minZoom: '0' 324 | maxZoom: '21' 325 | className: "nokia_normal_day" 326 | attribution: "©2012 Nokia Terms of use" 327 | name: 'Nokia normal Day' 328 | terrain_day: 329 | url: 'https://maps.nlp.nokia.com/maptiler/v2/maptile/newest/terrain.day/{z}/{x}/{y}/256/png8?lg=eng&token=A7tBPacePg9Mj_zghvKt9Q&app_id=KuYppsdXZznpffJsKT24' 330 | minZoom: '0' 331 | maxZoom: '21' 332 | className: "nokia_terrain_day" 333 | attribution: "©2012 Nokia Terms of use" 334 | name: 'Nokia Terrain Day' 335 | satellite_day: 336 | url: 'https://maps.nlp.nokia.com/maptiler/v2/maptile/newest/satellite.day/{z}/{x}/{y}/256/png8?lg=eng&token=A7tBPacePg9Mj_zghvKt9Q&app_id=KuYppsdXZznpffJsKT24' 337 | minZoom: '0' 338 | maxZoom: '21' 339 | className: "nokia_satellite_day" 340 | attribution: "©2012 Nokia Terms of use" 341 | name: 'Nokia Satellite Day' 342 | hybrid_day: 343 | url: 'https://maps.nlp.nokia.com/maptiler/v2/maptile/newest/hybrid.day/{z}/{x}/{y}/256/png8?lg=eng&token=A7tBPacePg9Mj_zghvKt9Q&app_id=KuYppsdXZznpffJsKT24' 344 | minZoom: '0' 345 | maxZoom: '21' 346 | className: "nokia_hybrid_day" 347 | attribution: "©2012 Nokia Terms of use" 348 | name: 'Nokia hybrid Day' 349 | CARTO: 350 | positron_rainbow_labels: 351 | default: true 352 | url: 'http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png' 353 | subdomains: 'abcd' 354 | minZoom: '0' 355 | maxZoom: '18' 356 | name: 'Positron' 357 | className: 'positron_rainbow_labels' 358 | attribution: '© OpenStreetMap contributors © CARTO' 359 | labels: 360 | url: 'http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png' 361 | dark_matter_rainbow_labels: 362 | url: 'http://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png' 363 | subdomains: 'abcd' 364 | minZoom: '0' 365 | maxZoom: '18' 366 | name: 'Dark matter' 367 | className: 'dark_matter_rainbow_labels' 368 | attribution: '© OpenStreetMap contributors © CARTO' 369 | labels: 370 | url: 'http://{s}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}.png' 371 | positron_rainbow: 372 | url: 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png' 373 | subdomains: 'abcd' 374 | minZoom: '0' 375 | maxZoom: '18' 376 | name: 'Positron (labels below)' 377 | className: 'positron_rainbow' 378 | attribution: '© OpenStreetMap contributors © CARTO' 379 | dark_matter_rainbow: 380 | url: 'http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png' 381 | subdomains: 'abcd' 382 | minZoom: '0' 383 | maxZoom: '18' 384 | name: 'Dark matter (labels below)' 385 | className: 'dark_matter_rainbow' 386 | attribution: '© OpenStreetMap contributors © CARTO' 387 | positron_lite_rainbow: 388 | url: 'http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png' 389 | subdomains: 'abcd' 390 | minZoom: '0' 391 | maxZoom: '18' 392 | name: 'Positron (lite)' 393 | className: 'positron_lite_rainbow' 394 | attribution: '© OpenStreetMap contributors © CARTO' 395 | dark_matter_lite_rainbow: 396 | url: 'http://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png' 397 | subdomains: 'abcd' 398 | minZoom: '0' 399 | maxZoom: '18' 400 | name: 'Dark matter (lite)' 401 | className: 'dark_matter_lite_rainbow' 402 | attribution: '© OpenStreetMap contributors © CARTO' 403 | eco_cartodb: 404 | url: 'https://cartocdn_{s}.global.ssl.fastly.net/base-antique/{z}/{x}/{y}.png' 405 | subdomains: 'abcd' 406 | minZoom: '0' 407 | maxZoom: '10' 408 | name: 'CARTO World Eco' 409 | className: 'eco_cartodb' 410 | attribution: '' 411 | flat_blue: 412 | url: 'https://cartocdn_{s}.global.ssl.fastly.net/base-flatblue/{z}/{x}/{y}.png' 413 | subdomains: 'abcd' 414 | minZoom: '0' 415 | maxZoom: '10' 416 | name: 'CARTO World Flat Blue' 417 | className: 'flat_blue' 418 | attribution: '' 419 | midnight_cartodb: 420 | url: 'https://cartocdn_{s}.global.ssl.fastly.net/base-midnight/{z}/{x}/{y}.png' 421 | subdomains: 'abcd' 422 | minZoom: '0' 423 | maxZoom: '10' 424 | name: 'CARTO World Midnight Commander' 425 | className: 'midnight_cartodb' 426 | attribution: '' 427 | antique_cartodb: 428 | url: 'https://cartocdn_{s}.global.ssl.fastly.net/base-antique/{z}/{x}/{y}.png' 429 | subdomains: 'abcd' 430 | minZoom: 0 431 | maxZoom: 10 432 | name: 'CARTO World Antique' 433 | className: 'antique_cartodb' 434 | attribution: '' 435 | Stamen: 436 | toner_stamen_labels: 437 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.png' 438 | subdomains: 'abcd' 439 | minZoom: '0' 440 | maxZoom: '18' 441 | name: 'Toner' 442 | className: 'toner_stamen_labels' 443 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 444 | labels: 445 | url: 'https://{s}.tile.stamen.com/toner-labels/{z}/{x}/{y}.png' 446 | toner_stamen: 447 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png' 448 | subdomains: 'abcd' 449 | minZoom: '0' 450 | maxZoom: '18' 451 | name: 'Toner (labels below)' 452 | className: 'toner_stamen' 453 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 454 | toner_background_stamen: 455 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.png' 456 | subdomains: 'abcd' 457 | minZoom: '0' 458 | maxZoom: '18' 459 | name: 'Toner Background' 460 | className: 'toner_background_stamen' 461 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 462 | toner_lite_stamen: 463 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png' 464 | subdomains: 'abcd' 465 | minZoom: '0' 466 | maxZoom: '18' 467 | name: 'Toner Lite' 468 | className: 'toner_lite_stamen' 469 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 470 | toner_lines_stamen: 471 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lines/{z}/{x}/{y}.png' 472 | subdomains: 'abcd' 473 | minZoom: '0' 474 | maxZoom: '18' 475 | name: 'Toner Lines' 476 | className: 'toner_lines_stamen' 477 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 478 | toner_hybrid_stamen: 479 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-hybrid/{z}/{x}/{y}.png' 480 | subdomains: 'abcd' 481 | minZoom: '0' 482 | maxZoom: '18' 483 | name: 'Toner Hybrid' 484 | className: 'toner_hybrid_stamen' 485 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 486 | watercolor_stamen: 487 | url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png' 488 | subdomains: 'abcd' 489 | minZoom: '0' 490 | maxZoom: '18' 491 | name: 'Watercolor' 492 | className: 'watercolor_stamen' 493 | attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.' 494 | overviews: 495 | min_rows: 2000000 496 | statement_timeout: 1800000 497 | tolerance_px: 1.0 498 | 499 | development: 500 | <<: *defaults 501 | #http_port: 3000 502 | varnish_management: 503 | critical: false 504 | host: '127.0.0.1' 505 | port: 6082 506 | purge_command: 'purge' 507 | url_purge_command: 'url.purge' 508 | retries: 5 509 | timeout: 5 510 | enforce_non_empty_layer_css: false 511 | 512 | test: 513 | <<: *defaults 514 | http_port: 53716 515 | redis: 516 | host: '127.0.0.1' 517 | port: 6335 518 | enforce_non_empty_layer_css: false 519 | api_requests_es_service: 520 | url: "http://api-calls-service.cartodb.localhost/search" 521 | body: "" 522 | 523 | staging: 524 | <<: *defaults 525 | 526 | production: 527 | <<: *defaults 528 | -------------------------------------------------------------------------------- /config/cartodb.nginx.proxy.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name yourdomain.com; 4 | return 301 https://$server_name$request_uri; 5 | } 6 | 7 | server { 8 | 9 | server_name yourdomain.com; 10 | 11 | listen 443 ssl; 12 | 13 | ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; 14 | ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; 15 | 16 | 17 | client_max_body_size 100M; 18 | 19 | location ~* /(user/.*/)?api/v1/maps { 20 | proxy_set_header Host $host; 21 | proxy_set_header X-Real-IP $remote_addr; 22 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 23 | proxy_set_header X-Forwarded-Proto $scheme; 24 | proxy_pass http://127.0.0.1:3000; 25 | } 26 | 27 | location ~* /(user/.*/)?api/v1/map { 28 | proxy_set_header Host $host; 29 | proxy_set_header X-Real-IP $remote_addr; 30 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 31 | proxy_set_header X-Forwarded-Proto $scheme; 32 | proxy_pass http://127.0.0.1:8181; 33 | } 34 | 35 | location ~* /(user/.*)?/api/v2/sql { 36 | # RedHog: Hack to work around bug in cartodb local hosting but using cdn for js libs 37 | rewrite /(user/.*)?/api/v2/sql(.*) /$1/api/v2/sql$2 break; 38 | proxy_set_header Host $host; 39 | proxy_set_header X-Real-IP $remote_addr; 40 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 41 | proxy_set_header X-Forwarded-Proto $scheme; 42 | 43 | # Change default timeout for your long-running SQL api calls! 44 | proxy_read_timeout 300s; 45 | 46 | proxy_pass http://127.0.0.1:8080; 47 | } 48 | 49 | location / { 50 | proxy_set_header Host $host; 51 | proxy_set_header X-Real-IP $remote_addr; 52 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 53 | proxy_set_header X-Forwarded-Proto $scheme; 54 | proxy_pass http://127.0.0.1:3000; 55 | } 56 | 57 | error_log /var/log/nginx/cartodb_error.log; 58 | access_log /var/log/nginx/cartodb_access.log; 59 | } 60 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | production: 2 | adapter: postgres 3 | encoding: unicode 4 | host: localhost 5 | port: 5432 6 | database: carto_db_production 7 | username: postgres 8 | password: 9 | conn_validator_timeout: 900 10 | 11 | staging: 12 | adapter: postgres 13 | encoding: unicode 14 | host: localhost 15 | port: 5432 16 | database: carto_db_staging 17 | username: postgres 18 | password: 19 | conn_validator_timeout: 900 20 | 21 | development: 22 | adapter: postgres 23 | encoding: unicode 24 | host: localhost 25 | port: 5432 26 | database: carto_db_development 27 | username: postgres 28 | password: 29 | conn_validator_timeout: 900 30 | 31 | test: 32 | adapter: postgres 33 | encoding: unicode 34 | database: carto_db_test 35 | host: localhost 36 | port: 5432 37 | username: postgres 38 | password: 39 | conn_validator_timeout: -1 40 | 41 | -------------------------------------------------------------------------------- /config/grunt_production.json: -------------------------------------------------------------------------------- 1 | { 2 | "use_minify": true, 3 | "http_path_prefix": "//cartodb-libs.global.ssl.fastly.net/cartodbui" 4 | } 5 | -------------------------------------------------------------------------------- /config/varnish: -------------------------------------------------------------------------------- 1 | # Configuration file for varnish 2 | # 3 | # /etc/init.d/varnish expects the variables $DAEMON_OPTS, $NFILES and $MEMLOCK 4 | # to be set from this shell script fragment. 5 | # 6 | 7 | # Should we start varnishd at boot? Set to "no" to disable. 8 | START=yes 9 | 10 | # Maximum number of open files (for ulimit -n) 11 | NFILES=131072 12 | 13 | # Maximum locked memory size (for ulimit -l) 14 | # Used for locking the shared memory log in memory. If you increase log size, 15 | # you need to increase this number as well 16 | MEMLOCK=82000 17 | 18 | # Default varnish instance name is the local nodename. Can be overridden with 19 | # the -n switch, to have more instances on a single server. 20 | # INSTANCE=$(uname -n) 21 | 22 | # This file contains 4 alternatives, please use only one. 23 | 24 | ## Alternative 1, Minimal configuration, no VCL 25 | # 26 | # Listen on port 6081, administration on localhost:6082, and forward to 27 | # content server on localhost:8080. Use a 1GB fixed-size cache file. 28 | # 29 | # DAEMON_OPTS="-a :6081 \ 30 | # -T localhost:6082 \ 31 | # -b localhost:8080 \ 32 | # -u varnish -g varnish \ 33 | # -S /etc/varnish/secret \ 34 | # -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G" 35 | 36 | 37 | ## Alternative 2, Configuration with VCL 38 | # 39 | # Listen on port 6081, administration on localhost:6082, and forward to 40 | # one content server selected by the vcl file, based on the request. Use a 1GB 41 | # fixed-size cache file. 42 | # 43 | DAEMON_OPTS="-a :6081 \ 44 | -T localhost:6082 \ 45 | -f /etc/varnish/default.vcl \ 46 | -s malloc,256m" 47 | 48 | 49 | ## Alternative 3, Advanced configuration 50 | # 51 | # See varnishd(1) for more information. 52 | # 53 | # # Main configuration file. You probably want to change it :) 54 | # VARNISH_VCL_CONF=/etc/varnish/default.vcl 55 | # 56 | # # Default address and port to bind to 57 | # # Blank address means all IPv4 and IPv6 interfaces, otherwise specify 58 | # # a host name, an IPv4 dotted quad, or an IPv6 address in brackets. 59 | # VARNISH_LISTEN_ADDRESS= 60 | # VARNISH_LISTEN_PORT=6081 61 | # 62 | # # Telnet admin interface listen address and port 63 | # VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 64 | # VARNISH_ADMIN_LISTEN_PORT=6082 65 | # 66 | # # The minimum number of worker threads to start 67 | # VARNISH_MIN_THREADS=1 68 | # 69 | # # The Maximum number of worker threads to start 70 | # VARNISH_MAX_THREADS=1000 71 | # 72 | # # Idle timeout for worker threads 73 | # VARNISH_THREAD_TIMEOUT=120 74 | # 75 | # # Cache file location 76 | # VARNISH_STORAGE_FILE=/var/lib/varnish/$INSTANCE/varnish_storage.bin 77 | # 78 | # # Cache file size: in bytes, optionally using k / M / G / T suffix, 79 | # # or in percentage of available disk space using the % suffix. 80 | # VARNISH_STORAGE_SIZE=1G 81 | # 82 | # # File containing administration secret 83 | # VARNISH_SECRET_FILE=/etc/varnish/secret 84 | # 85 | # # Backend storage specification 86 | # VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}" 87 | # 88 | # # Default TTL used when the backend does not specify one 89 | # VARNISH_TTL=120 90 | # 91 | # # DAEMON_OPTS is used by the init script. If you add or remove options, make 92 | # # sure you update this section, too. 93 | # DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \ 94 | # -f ${VARNISH_VCL_CONF} \ 95 | # -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \ 96 | # -t ${VARNISH_TTL} \ 97 | # -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \ 98 | # -S ${VARNISH_SECRET_FILE} \ 99 | # -s ${VARNISH_STORAGE}" 100 | # 101 | 102 | 103 | ## Alternative 4, Do It Yourself 104 | # 105 | # DAEMON_OPTS="" 106 | -------------------------------------------------------------------------------- /create_user: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | SUBDOMAIN="admin" 6 | PASSWORD="pass1234" 7 | ADMIN_PASSWORD="pass1234" 8 | EMAIL="dev@example.com" 9 | 10 | echo "--- Create '${SUBDOMAIN}' user" 11 | bundle exec rake cartodb:db:create_user --trace SUBDOMAIN="${SUBDOMAIN}" \ 12 | PASSWORD="${PASSWORD}" ADMIN_PASSWORD="${ADMIN_PASSWORD}" \ 13 | EMAIL="${EMAIL}" 14 | 15 | # # Update your quota to 100GB 16 | echo "--- Updating quota to 100GB" 17 | bundle exec rake cartodb:db:set_user_quota["${SUBDOMAIN}",102400] 18 | 19 | # # Allow unlimited tables to be created 20 | echo "--- Allowing unlimited tables creation" 21 | bundle exec rake cartodb:db:set_unlimited_table_quota["${SUBDOMAIN}"] 22 | 23 | # # Allow user to create private tables in addition to public 24 | echo "--- Allowing private tables creation" 25 | bundle exec rake cartodb:db:set_user_private_tables_enabled["${SUBDOMAIN}",'true'] 26 | 27 | # # Set the account type 28 | echo "--- Setting cartodb account type" 29 | bundle exec rake cartodb:db:set_user_account_type["${SUBDOMAIN}",'[DEDICATED]'] 30 | -------------------------------------------------------------------------------- /setup_organization.sh: -------------------------------------------------------------------------------- 1 | cd /cartodb 2 | source /usr/local/rvm/scripts/rvm 3 | 4 | echo "INSERT INTO feature_flags (id,name, restricted) VALUES (nextval('machine_added_feature_flags_id_seq'), 'editor-3', false);" | psql -U postgres carto_db_development && \ 5 | echo "INSERT INTO feature_flags (id,name, restricted) VALUES (nextval('machine_added_feature_flags_id_seq'), 'explore_site', false);" | psql -U postgres carto_db_development && \ 6 | 7 | ORGANIZATION_NAME="example" 8 | USERNAME="admin4example" 9 | EMAIL="admin@example.com" 10 | PASSWORD="pass1234" 11 | 12 | bundle exec rake cartodb:db:create_user EMAIL="${EMAIL}" PASSWORD="${PASSWORD}" SUBDOMAIN="${USERNAME}" 13 | bundle exec rake cartodb:db:set_unlimited_table_quota["${USERNAME}"] 14 | bundle exec rake cartodb:db:create_new_organization_with_owner ORGANIZATION_NAME="${ORGANIZATION_NAME}" USERNAME="${USERNAME}" ORGANIZATION_SEATS=100 ORGANIZATION_QUOTA=102400 ORGANIZATION_DISPLAY_NAME="${ORGANIZATION_NAME}" 15 | bundle exec rake cartodb:db:set_organization_quota[$ORGANIZATION_NAME,100] 16 | -------------------------------------------------------------------------------- /startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PORT=3000 4 | 5 | service postgresql start 6 | service redis-server start 7 | service varnish start 8 | 9 | cd /Windshaft-cartodb 10 | node app.js production & 11 | 12 | cd /CartoDB-SQL-API 13 | node app.js production & 14 | 15 | cd /cartodb 16 | source /usr/local/rvm/scripts/rvm 17 | bundle exec script/restore_redis 18 | bundle exec script/resque > resque.log 2>&1 & 19 | bundle exec rails s -p $PORT 20 | --------------------------------------------------------------------------------