How to install elastic/kibana/logstash in custom path?

I need to install Elasticsearch in /opt/elasticsearch, kibana and logstash like this. And then autostart via systemctl.
So, I tried like this Install Elasticsearch with RPM | Elasticsearch Reference [6.2] | Elastic
I exported ES_HOME and ES_PATH_CONF

export ES_HOME=/opt/elasticsearch 
export ES_PATH_CONF=/opt/elasticsearch/config

and launch rpm install.
But paths wasn't changed it still installed in /usr/share/elasicsearch and config path /etc/elasticsearch

I tried manually installation throw tar.gz. If I correctly understand, there isn't available autostart. How can I install systemd module into the ES serverinstalled from the archive?

So How can I install ELK in custom path. My customer want ELK in /opt/ folder.

The variables you set have no impact in the installation, only when running, the rpm package will always install in the default locations.

If you want to use a custom path, you need to use the .tar.gz version, you will need to untar the files in the directories you want and create the autostart files manually, it is also recommended to create an user for each service and use that user to start the services.

There are a lot of documentations on how to create a systemd startup file, you can check for example this answer in stackexchange, you can also use the original elasticsearch.service and edit the variables according to your paths.

I wrote startup file

    [Unit]
    Description=Elasticsearch
    Documentation=https://www.elastic.co
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    Type=notify
    RuntimeDirectory=elasticsearch
    PrivateTmp=true
    Environment=ES_HOME=/opt/elasticsearch
    Environment=ES_PATH_CONF=/opt/elasticsearch/config
    Environment=PID_DIR=/var/run/elasticsearch
    Environment=ES_SD_NOTIFY=true
    EnvironmentFile=-/etc/sysconfig/elasticsearch
    
    WorkingDirectory=/opt/elasticsearch
    
    User=elasticsearch
    Group=elasticsearch
    
    ExecStart=/opt/elasticsearch/bin/elasticsearch -p ${PID_DIR}/elasticsearch.pid --quiet
    
    # StandardOutput is configured to redirect to journalctl since
    # some error messages may be logged in standard output before
    # elasticsearch logging system is initialized. Elasticsearch
    # stores its logs in /var/log/elasticsearch and does not use
    # journalctl by default. If you also want to enable journalctl
    # logging, you can simply remove the "quiet" option from ExecStart.
    StandardOutput=journal
    StandardError=inherit
    
    # Specifies the maximum file descriptor number that can be opened by this process
    LimitNOFILE=65535
    
    # Specifies the maximum number of processes
    # Specifies the maximum number of processes
    LimitNPROC=4096
    
    # Specifies the maximum size of virtual memory
    LimitAS=infinity
    
    # Specifies the maximum file size
    LimitFSIZE=infinity
    
    # Disable timeout logic and wait until process is stopped
    TimeoutStopSec=0
    
    # SIGTERM signal is used to stop the Java process
    KillSignal=SIGTERM
    
    # Send the signal only to the JVM rather than its control group
    KillMode=process
    
    # Java process is never killed
    SendSIGKILL=no
    
    # When a JVM receives a SIGTERM signal it exits with code 143
    SuccessExitStatus=143
    
    # Allow a slow startup before the systemd notifier module kicks in to extend the timeout
    TimeoutStartSec=5000
    
    [Install]
    WantedBy=multi-user.target

But it doesn't start, doesn't crash, and doesn't write any logs in journalctl.

Look at the system logs, /var/log/messages for red hat based and /var/log/syslog for debian based.

Also, what are the path.data and path.logs in your elasticsearch.yml file?

It terminated by timeout

2021-10-11T15:44:06.372123+03:00 el5 systemd[1]: elasticsearch.service: Start operation timed out. Terminating.
2021-10-11T15:44:06.480782+03:00 el5 systemd[1]: Failed to start Elasticsearch.
2021-10-11T15:44:06.481219+03:00 el5 systemd[1]: elasticsearch.service: Unit entered failed state.
2021-10-11T15:44:06.481465+03:00 el5 systemd[1]: elasticsearch.service: Failed with result 'timeout'.
el5:~ # tree /opt/elasticsearch/data/nodes
/opt/elasticsearch/data/nodes
└── 0
    ├── node.lock
    └── _state
        ├── _16.cfe
        ├── _16.cfs
        ├── _16.si
        ├── node-1.st
        ├── segments_1a
        └── write.lock
el5:~ # tail -n 100 /opt/elasticsearch/config/elasticsearch.yml 
# ======================== Elasticsearch Configuration =========================
#
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
#       Before you set out to tweak and tune the configuration, make sure you
#       understand what are you trying to accomplish and the consequences.
#
# The primary way of configuring a node is via this file. This template lists
# the most important settings you may want to configure for a production cluster.
#
# Please consult the documentation for further information on configuration options:
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
#cluster.name: my-application
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
#node.name: node-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
#path.data: /path/to/data
#
# Path to log files:
#
#path.logs: /path/to/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# By default Elasticsearch is only accessible on localhost. Set a different
# address here to expose this node on the network:
#
#network.host: 192.168.0.1
#
# By default Elasticsearch listens for HTTP traffic on the first free port it
# finds starting at 9200. Set a specific HTTP port here:
#
#http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.seed_hosts: ["host1", "host2"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
#cluster.initial_master_nodes: ["node-1", "node-2"]
#
# For more information, consult the discovery and cluster formation module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true
#
cluster.name: elk1
node.name: ${HOSTNAME}
node.roles: [ master, remote_cluster_client ]
path.data: /opt/elasticsearch/data
path.logs: /opt/elasticsearch/logs
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["172.29.39.145", "172.29.39.146", "172.29.39.147", "172.29.39.148"]
cluster.initial_master_nodes: ["172.29.39.145"]
action.auto_create_index: .monitoring*,.watches,.triggered_watches,.watcher-history*,.ml*
el5:~ # tail -f /opt/elasticsearch/logs/elk1.log 
[2021-10-11T15:59:12,881][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [metrics]
[2021-10-11T15:59:13,313][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [synthetics]
[2021-10-11T15:59:13,740][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [watch-history-ilm-policy]
[2021-10-11T15:59:14,006][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [ilm-history-ilm-policy]
[2021-10-11T15:59:14,206][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [slm-history-ilm-policy]
[2021-10-11T15:59:14,490][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [.fleet-actions-results-ilm-policy]
[2021-10-11T15:59:14,836][INFO ][o.e.x.i.a.TransportPutLifecycleAction] [el5] adding index lifecycle policy [.deprecation-indexing-ilm-policy]
[2021-10-11T15:59:15,067][INFO ][o.e.l.LicenseService     ] [el5] license [f28f0881-f22b-4878-912b-6a8816d2dc5a] mode [basic] - valid
[2021-10-11T15:59:15,069][INFO ][o.e.x.s.s.SecurityStatusChangeListener] [el5] Active license is now [BASIC]; Security is disabled
[2021-10-11T15:59:15,070][WARN ][o.e.x.s.s.SecurityStatusChangeListener] [el5] Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security.
el5:~ # tree /opt/elasticsearch/logs/
/opt/elasticsearch/logs/
├── elk1_audit.json
├── elk1_deprecation.json
├── elk1_deprecation.log
├── elk1_index_indexing_slowlog.json
├── elk1_index_indexing_slowlog.log
├── elk1_index_search_slowlog.json
├── elk1_index_search_slowlog.log
├── elk1.log
├── elk1_server.json
├── gc.log
├── gc.log.00
├── gc.log.01
└── gc.log.02